Are cpBody automaticall collidable?

Official forum for the Chipmunk2D Physics Library.
Post Reply
Munchor
Posts: 2
Joined: Wed Oct 30, 2013 3:58 pm
Contact:

Are cpBody automaticall collidable?

Post by Munchor »

I've used Chipmunk JS before and my cpBodies would automatically collide would each other. However, I'm now trying the C version using Allegro to display items and I'm not really being able to make my cpBodies collide against each other.

Here is my full source code:

Code: Select all

#include <stdio.h>
#include <allegro5/allegro.h>
#include <chipmunk/chipmunk.h>

const float FPS = 60.0;
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BOUNCER_SIZE = 32;
int keys[ALLEGRO_KEY_MAX];
cpVect mouse;
cpBody *blocks[32];
cpSpace *space;
int n_blocks;

void add_block()
{
  cpFloat radius = 5;
  cpFloat mass = 1;
  cpFloat moment = cpMomentForCircle(mass, 0, radius, cpvzero);

  cpBody *newBody = cpSpaceAddBody(space, cpBodyNew(mass, moment));
  cpBodySetPos(newBody, cpv(mouse.x, mouse.y));

  cpShape *newShape = cpSpaceAddShape(space, cpCircleShapeNew(newBody,
                                                              radius,
                                                              cpvzero));

  cpShapeSetFriction(newShape, 1);

  blocks[n_blocks++] = newBody;
}

int main(int argc, char **argv)
{
  mouse = cpv(0, 0);
  cpVect gravity = cpv(0, 100);

  space = cpSpaceNew();
  cpSpaceSetGravity(space, gravity);

  cpShape *ground = cpSegmentShapeNew(space->staticBody, cpv(0, 300),
                                      cpv(300, 300), 0);
  cpShapeSetFriction(ground, 1);
  cpSpaceAddShape(space, ground);

  n_blocks = 0;

  cpFloat timeStep = 1.0 / FPS;

  ALLEGRO_DISPLAY *display = NULL;
  ALLEGRO_EVENT_QUEUE *event_queue = NULL;
  ALLEGRO_TIMER *timer = NULL;
  ALLEGRO_BITMAP *bouncer = NULL;
  bool redraw = true;
  bool doexit = false;

  if (!al_init()) {
    fprintf(stderr, "Failed to initialize allegro!\n");
    return -1;
  }

  if (!al_install_keyboard()) {
    fprintf(stderr, "Failed to initialize the keyboard!\n");
    return -1;
  }

  if (!al_install_mouse()) {
    fprintf(stderr, "Failed to initialize the mouse!\n");
    return -1;
  }

  timer = al_create_timer(1.0 / FPS);
  if (!timer) {
    fprintf(stderr, "Failed to create timer!\n");
    return -1;
  }

  display = al_create_display(SCREEN_W, SCREEN_H);
  if (!display) {
    fprintf(stderr, "Failed to create display!\n");
    al_destroy_timer(timer);
    return -1;
  }

  bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
  if (!bouncer) {
    fprintf(stderr, "Failed to create bouncer bitmap!\n");
    al_destroy_display(display);
    al_destroy_timer(timer);
    return -1;
  }

  al_set_target_bitmap(bouncer);
  al_clear_to_color(al_map_rgb(255, 0, 255));
  al_set_target_bitmap(al_get_backbuffer(display));

  event_queue = al_create_event_queue();
  if (!event_queue) {
    fprintf(stderr, "Failed to create event_queue!\n");
    al_destroy_bitmap(bouncer);
    al_destroy_display(display);
    al_destroy_timer(timer);
    return -1;
  }

  al_register_event_source(event_queue, al_get_display_event_source(display));
  al_register_event_source(event_queue, al_get_timer_event_source(timer));
  al_register_event_source(event_queue, al_get_mouse_event_source());
  al_register_event_source(event_queue, al_get_keyboard_event_source());
  al_clear_to_color(al_map_rgb(0,0,0));
  al_flip_display();
  al_start_timer(timer);

  while (!doexit)
  {
    cpSpaceStep(space, timeStep);
    //cpVect pos = cpBodyGetPos(ballBody);

    ALLEGRO_EVENT ev;
    al_wait_for_event(event_queue, &ev);

    if (ev.type == ALLEGRO_EVENT_TIMER) {
      if (keys[ALLEGRO_KEY_LEFT]) {
        //pos.x -= 2;
        //cpBodySetPos(ballBody, pos);
      }

      if (keys[ALLEGRO_KEY_RIGHT]) {
        //pos.x += 2;
        //cpBodySetPos(ballBody, pos);
      }

      redraw = true;
    } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
      break;
    } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
      keys[ev.keyboard.keycode] = true;
    } else if (ev.type == ALLEGRO_EVENT_KEY_UP) {
      keys[ev.keyboard.keycode] = false;
    } else if (ev.type == ALLEGRO_EVENT_MOUSE_AXES ||
               ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) {
      mouse.x = ev.mouse.x;
      mouse.y = ev.mouse.y;
    } else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
      add_block();
    }

    if (redraw && al_is_event_queue_empty(event_queue)) {
      redraw = false;
      al_clear_to_color(al_map_rgb(0, 0, 0));

      int i;
      for (i = 0; i < n_blocks; i++) {
        cpVect pos = cpBodyGetPos(blocks[i]);
        al_draw_bitmap(bouncer, pos.x, pos.y, 0);
      }

      al_flip_display();
    }
  }

  al_destroy_bitmap(bouncer);
  al_destroy_timer(timer);
  al_destroy_display(display);
  al_destroy_event_queue(event_queue);

  cpShapeFree(ground);
  cpSpaceFree(space);

  return 0;
}
Basically, I use the mouse to add new blocks to the screen and they should fall on top of each other. Instead they all just collide with the ground and not with each other.

Besides, I wonder if in Chipmunk the X and Y coordinates of bodies and shapes are the center of the object or the top left corner or something else. I couldn't find much information on that.

Any ideas? Thank you in advance.

Edit: I put up a better version of the source code here.
Munchor
Posts: 2
Joined: Wed Oct 30, 2013 3:58 pm
Contact:

Re: Are cpBody automaticall collidable?

Post by Munchor »

Alright, I reckon I got it:

Code: Select all

void add_block()
{
  cpFloat radius = 5;
  cpFloat mass = 1;
  cpFloat moment = cpMomentForBox(mass, 32, 32);

  cpBody *newBody = cpSpaceAddBody(space, cpBodyNew(mass, moment));
  cpBodySetPos(newBody, cpv(mouse.x, mouse.y));

  cpShape *newShape = cpSpaceAddShape(space, cpBoxShapeNew(newBody,
                                                           32, 32));

  cpShapeSetFriction(newShape, 1);

  blocks[n_blocks++] = newBody;
}
I just had to change to using a Box, not a CircleShape and cpMomentForBox as opposed to cpMomentForCircle.

Much better now, but I still have to fix my angle when drawing. I'll try and figure out how I can get the angle of a cpBody.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Are cpBody automaticall collidable?

Post by slembcke »

cpBodyGetAngle(body) returns the rotation of the body in radians. If you don't want the box to rotate, you can give it INFINITY for the moment of inertia.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Post Reply

Who is online

Users browsing this forum: No registered users and 9 guests