object_type_t *add_object(coordinate_t coordinate,object_t object,dir_t dir,standpoint_t standpoint,int number,object_type_t *object_type)
{
	object_type_t *ot=object_type;
	object_type_t *ret=NULL;

	do{
		if(NULL==ot){
			break;
		}

		switch(object){
			case OBJECT_TANK:
				ret=add_tank(coordinate,dir,standpoint,number,ot);
				break;
			case OBJECT_BULLET:
				ret=add_bullet(coordinate,dir,standpoint,ot);
				break;
			case OBJECT_BARRIER:
				ret=add_barrier(coordinate,ot);
				break;
		}
	}while(0);
	
	return ret;
}
Beispiel #2
0
//posun hry o casovy tik
void update_game(float time, int k_up, int k_down, int k_right, int k_left, int k_fire) {
	//pozadi pro koncovy screen hry
	if (playerdead) { 
		move_stars(time);
		move_enemies(time);
		move_bullets(time);
		update_particles(time);
		move_bonuses(time);

		deathtimer-=time;
		if ((deathtimer<=0) && k_fire) { 
			//zacatek nove hry
			finish_game();
			init_game();
		}
	}

	else {
		handle_levels();
		
		//odecteni casu od casovacu bonusu
		shieldtimer-=time;
		canontimer-=time;

		reload+=time;

		//ovladani raketky (funkce z main.c)
		if (k_left) speedx-=time*1300;
		if (k_right) speedx+=time*1300;
		if (k_up) speedy+=time*1300;
		if (k_down) speedy-=time*1300;

		//strelba mozna jen po specifickem casovem intervalu 
		if (k_fire && ((canontimer>0)?(reload>(0.2/(plevel))):(reload>(0.5/(plevel*0.9))))) { 
			if (canontimer<=0)
				//strelba zavisla na power levelu
				add_bullet(posx, posy+50, 0, 200, plevel, 1, 1);
			else 
				//silenej gun po sebrani zeleneho bonusu
				add_bullet(posx, posy+50, 0.8*speedx+200*DFRAND*DFRAND*DFRAND, 300+speedy+20*DFRAND, 10*plevel, 1, 1); 
			reload=0;
		}
		
		//aplikace rychlosti raketky na pozici
		posx+=speedx*time;
		posy+=speedy*time;

		//aby raketka brzdila stejne pri ruznem frameratu
		speedx*=powf(0.02, time); //powf = exponenciela
		speedy*=powf(0.02, time);

		//okraje hraciho pole pro raketku
		if (posx<-225) {posx=-225; speedx=0;} 
		if (posx>225) {posx=225; speedx=0;}
		if (posy<-335) {posy=-335; speedy=0;}
		if (posy>-100) {posy=-100; speedy=0;}

		move_stars(time);
		move_enemies(time);
		move_bullets(time);
		update_particles(time);
		move_bonuses(time);
	}
}
Beispiel #3
0
static DskJsonValue *
create_user_update (User *user)
{
  Game *game = user->base.game;

  /* width/height in various units, rounded up */
  unsigned tile_width = (user->width + TILE_SIZE - 1) / TILE_SIZE;
  unsigned tile_height = (user->height + TILE_SIZE - 1) / TILE_SIZE;
  unsigned cell_width = (tile_width + CELL_SIZE * 2 - 2) / CELL_SIZE;
  unsigned cell_height = (tile_height + CELL_SIZE * 2 - 2) / CELL_SIZE;

  /* left/upper corner, rounded down */
  int min_tile_x = user->base.x - (tile_width+1) / 2;
  int min_tile_y = user->base.y - (tile_height+1) / 2;
  int min_cell_x = int_div (min_tile_x, CELL_SIZE);
  int min_cell_y = int_div (min_tile_y, CELL_SIZE);

  unsigned alloced = 16;
  DskJsonValue **elements = dsk_malloc (sizeof (DskJsonValue *) * alloced);
  unsigned n_elements = 0;

  unsigned x, y;

  for (x = 0; x < cell_width; x++)
    for (y = 0; y < cell_height; y++)
      {
        int ucx = x + min_cell_x;               /* un-wrapped x, y */
        int ucy = y + min_cell_y;
        int px = (ucx * CELL_SIZE - user->base.x) * TILE_SIZE + user->width / 2 - TILE_SIZE / 2;
        int py = (ucy * CELL_SIZE - user->base.y) * TILE_SIZE + user->height / 2 - TILE_SIZE / 2;
        unsigned cx, cy;
        Cell *cell;

        /* deal with wrapping (or not) */
        if (ucx < 0)
          {
            if (!game->wrap)
              continue;
            cx = ucx + game->universe_width;
          }
        else if ((unsigned) ucx >= game->universe_width)
          {
            cx = ucx;
            if (game->wrap)
              cx -= game->universe_width;
          }
        else
          cx = ucx;
        if (ucy < 0)
          {
            if (!game->wrap)
              continue;
            cy = ucy + game->universe_height;
          }
        else if ((unsigned) ucy >= game->universe_height)
          {
            cy = ucy;
            if (game->wrap)
              cy -= game->universe_height;
          }
        else
          cy = ucy;

        /* render walls */
        if (cy < game->universe_height && cx <= game->universe_width
            && game->v_walls[cx + cy * game->universe_width])
          {
            /* render vertical wall */
            add_wall (&n_elements, &elements, &alloced,
                      px, py, TILE_SIZE, TILE_SIZE * (CELL_SIZE+1));
          }
        if (cy <= game->universe_height && cx < game->universe_width
            && game->h_walls[cx + cy * game->universe_width])
          {
            /* render horizontal wall */
            add_wall (&n_elements, &elements, &alloced,
                      px, py, TILE_SIZE * (CELL_SIZE+1), TILE_SIZE);
          }
        if (cx >= game->universe_width || cy >= game->universe_height)
          continue;

        cell = game->cells + (game->universe_width * cy + cx);

        /* render bullets */
        Object *object;
        for (object = cell->objects[OBJECT_TYPE_BULLET]; object; object = object->next_in_cell)
          {
            int bx = px + (object->x - cx * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            int by = py + (object->y - cy * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            add_bullet (&n_elements, &elements, &alloced,
                        bx, by);
          }

        /* render dudes */
        for (object = cell->objects[OBJECT_TYPE_USER]; object; object = object->next_in_cell)
          {
            int bx = px + (object->x - cx * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            int by = py + (object->y - cy * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            add_user (&n_elements, &elements, &alloced,
                      bx, by, user == (User*) object);
          }

        /* render bad guys */
        for (object = cell->objects[OBJECT_TYPE_ENEMY]; object; object = object->next_in_cell)
          {
            int bx = px + (object->x - cx * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            int by = py + (object->y - cy * CELL_SIZE) * TILE_SIZE + TILE_SIZE / 2;
            add_enemy (&n_elements, &elements, &alloced, bx, by);
          }

        /* render generators */
        if (cell->generator)
          {
            int bx = px + (cell->generator->x - cx * CELL_SIZE) * TILE_SIZE + TILE_SIZE;
            int by = py + (cell->generator->y - cy * CELL_SIZE) * TILE_SIZE + TILE_SIZE;
            add_generator (&n_elements, &elements, &alloced, bx, by, user->base.game->latest_update);
          }
      }
  DskJsonValue *rv;
  rv = dsk_json_value_new_array (n_elements, elements);
  dsk_free (elements);

  user->last_update = game->latest_update;
  return rv;
}
Beispiel #4
0
int move_player1(ENTITY *e,int frame_time)
{
	int printinfo=FALSE;
	if(e==0)
		return 0;
	if(key_state('p')){
		switch(e->state_action){
		default:
			e->state_action=S_ACTION_PAUSE1;
			break;
		case S_ACTION_PAUSE3:
		case S_ACTION_PAUSE2:
			e->state_action=S_ACTION_PAUSE3;
			break;
		}
	}else{
		switch(e->state_action){
		default:
			e->state_action=0;
			break;
		case S_ACTION_PAUSE2:
		case S_ACTION_PAUSE1:
			e->state_action=S_ACTION_PAUSE2;
			break;
		}
	}
	if(e->state_action==S_ACTION_PAUSE1 || e->state_action==S_ACTION_PAUSE2)
		return 0;
	if(key_state(VK_LEFT)){
		//printf("delta=%i\n",delta);
		e->rotx=-1;
		e->speedx=frame_time/2;
	}
	else if(key_state(VK_RIGHT)){
		e->rotx=1;
		e->speedx=frame_time/2;
	}
	else{
		e->speedx-=frame_time;
	}
	if(key_state(VK_DOWN)){
		e->posz+=100;
		printinfo=TRUE;
	}
	if(key_state(VK_UP)){
		e->posz-=100;
		printinfo=TRUE;
	}

	if(key_state(VK_CONTROL)){
		e->speedy=frame_time;
	}
	else{
		e->speedy-=frame_time/6;
	}
	if(key_state(VK_MENU)){
		int s[3]={0,0,0},p[3]={0,0,0};
		if(e->rotx<0)
			s[0]=-2;
		else
			s[0]=2;
		p[0]=e->posx;
		p[1]=e->posy;
		p[2]=e->posz;
		if(e->state_action==0){
			e->state_action=S_ACTION_FIRE;
			e->stime_action=0;
			add_bullet(e,s,p);
		}
		printf("menu\n");
	}
	switch(e->state_action){
	case S_ACTION_FIRE:
		e->stime_action+=frame_time;
		if(e->stime_action>250)
			e->state_action=0;
		break;
	}

	if(e->speedx>100)
		e->speedx=100;
	else if(e->speedx<0)
		e->speedx=0;

	if(e->speedy>100)
		e->speedy=100;
	else if(e->speedy<-100)
		e->speedy=-100;
	
	e->posx+=e->speedx*e->rotx;

	e->posy+=e->speedy;

	//if(posz>100)
	//	posz=0;
	//else if(posz<0)
	//	posz=0;

	if(e->posx>500)
		e->posx=500;
	else if(e->posx<-500)
		e->posx=-500;

	if(e->posy>500)
		e->posy=500;
	else if(e->posy<-100){
		e->posy=-100;
		e->speedy=0;
	}

	if(e->speedx==0)
		e->frame=0;
	else{
		e->time+=e->speedx;
		if(e->time>12){
			e->time=0;
			e->frame++;
			if(e->frame>=(e->tcols*e->trows))
				e->frame=0;
		}
	}
//	if(e->speedx!=0 || e->speedy!=0 || e->speedz!=0 || printinfo)
//		printf("sx=% 5.1f sy=% 5.1f sz=% 5.1f px=% 5.1f py=% 5.1f pz=% 5.1f\n",e->speedx,e->speedy,e->speedz,e->posx,e->posy,e->posz);
	return 0;
}
Beispiel #5
0
void
run_play()
{
   sp1_ClearRectInv(&cr, BRIGHT | INK_WHITE | PAPER_BLACK, 32, SP1_RFLAG_TILE | SP1_RFLAG_COLOUR);
   sp1_UpdateNow();

   sp1_SetPrintPos(&ps0, 0, 0);
   sp1_PrintString(&ps0, ptiles);

   // setup the game
   sprites[PLAYER].x = 15 * 8;
   sprites[PLAYER].y = 20 * 8;
   sprites[PLAYER].frame = 0;
   sprites[PLAYER].delay = 0;
   sprites[PLAYER].sprite = player;
   update_player();

   horde_count = 0;
   wave_delay = 0;
   wave = 0;
   score = 0;
   lives = 3;
   invulnerable = 0;
   update_score();

   while(1)
   {
      // TODO: pause/resume

      if (in_inkey() == 12)
         // exit current game
         break;

      key = (joyfunc)(&joy_k);
      if (key & IN_STICK_LEFT && !(key & IN_STICK_RIGHT))
      {
         if (sprites[PLAYER].x - 4 > ORIGINX)
         {
            sprites[PLAYER].x -= 4;
            sprites[PLAYER].frame = 2;
            sprites[PLAYER].delay = 4;
            update_player();
         }
      }

      if (key & IN_STICK_RIGHT && !(key & IN_STICK_LEFT))
      {
         if (sprites[PLAYER].x + 16 + 8 + 4 < WIDTH)
         {
            sprites[PLAYER].x += 4;
            sprites[PLAYER].frame = 1;
            sprites[PLAYER].delay = 4;
            update_player();
         }
      }

      if (cooldown > 0)
         --cooldown;

      if (key & IN_STICK_FIRE && !cooldown)
      {
         // fire rate
         cooldown = 10;
         add_bullet(ST_BULLET, sprites[PLAYER].x + 4, sprites[PLAYER].y - 2);

         playfx(FX_FIRE);
      }

      // change the frame to normal?
      if (sprites[PLAYER].delay)
      {
         if (!--sprites[PLAYER].delay)
         {
            sprites[PLAYER].frame = 0;
            update_player();
         }
      }

      update_horde();
      update_sprites();
      update_script();

      if (invulnerable > 0)
      {
         // will be 0, but in case of "the unexpected"
         if (lives <= 0)
         {
            // GAME OVER

            // some noise
            playfx(FX_EXPLO);
            playfx(FX_EXPLO);
            playfx(FX_EXPLO);

            // we don't want the player to miss the game over music
            in_wait_nokey();

            sp1_SetPrintPos(&ps0, 11, 8);
            sp1_PrintString(&ps0, "\x14\x46" "G A M E  O V E R");
            sp1_UpdateNow();

            dzx7_standard(song2, TEMPMEM);
            ntropic_play(TEMPMEM, 0);

            for (i = 0; i < 32; ++i)
               wait();

            // leave the game
            break;
         }

         --invulnerable;
         update_player();
      }

      wait();
      intrinsic_halt();   // inline halt without impeding optimizer
      sp1_UpdateNow();
   }

   destroy_type_sprite(ST_ALL);
   collect_sprites();

   // the player sprite is never destroyed, so hide it
   sp1_MoveSprAbs(sprites[PLAYER].s, &cr, NULL, 0, 34, 0, 0);
   sp1_UpdateNow();

   sp1_ClearRectInv(&cr, BRIGHT | INK_BLACK | PAPER_BLACK, 32, SP1_RFLAG_TILE | SP1_RFLAG_COLOUR);
   sp1_UpdateNow();
}
Beispiel #6
0
void
update_sprites(void)
{
   for (sp_iter = sp_used; sp_iter; sp_iter = sp_iter->n)
   {
      if (!sp_iter->alive)
         continue;

      switch(sp_iter->type)
      {
         default:
            break;

         case ST_BULLET:

            sp_iter->x += sp_iter->ix;
            sp_iter->y += sp_iter->iy;

            // out of screen
            if(sp_iter->x < ORIGINX || sp_iter->x > WIDTH
                  || sp_iter->y + 8 < ORIGINY || sp_iter->y > HEIGHT)
            {
               remove_sprite(sp_iter);
               // no drawing required
               break;
            }

            // enemy check
            for (sp_iter2 = sp_used; sp_iter2; sp_iter2 = sp_iter2->n)
               if (sp_iter2->type == ST_ENEMY && sp_iter2->alive
                     && sp_iter->x + 4 < sp_iter2->x + 16
                     && sp_iter2->x < sp_iter->x + 4
                     && sp_iter->y + 4 < sp_iter2->y + 16
                     && sp_iter2->y < sp_iter->y + 4)
               {
                  score += 25;
                  if (score > hi_score)
                     hi_score = score;

                  update_score();

                  // convert into an explosion
                  sp_iter2->sprite = explosion;
                  sp_iter2->frame = 0;
                  sp_iter2->delay = 0;
                  sp_iter2->type = ST_EXPLO;

                  playfx(FX_EXPLO);

                  // remove the bullet
                  remove_sprite(sp_iter);

                  // one less enemy
                  --horde_count;
               }

            // draw only if it didn't hit anything
            if (sp_iter->alive)
               sp1_MoveSprPix(sp_iter->s, &cr, sp_iter->sprite, 8 + sp_iter->x, 8 + sp_iter->y);
            
            break;

         case ST_EBULLET:

            sp_iter->y += sp_iter->iy;

            // out of screen
            if (sp_iter->y > HEIGHT)
            {
               remove_sprite(sp_iter);
               // no drawing required
               break;
            }

            // player check
            if (!invulnerable && sp_iter->x + 4 < sprites[PLAYER].x + 16
                  && sprites[PLAYER].x < sp_iter->x + 4
                  && sp_iter->y + 4 < sprites[PLAYER].y + 16
                  && sprites[PLAYER].y < sp_iter->y + 4)
            {
               // convert into an explosion
               sp_iter->sprite = impact + 2 * 4 * 8;
               sp_iter->frame = 0;
               sp_iter->delay = 0;
               sp_iter->type = ST_HIT;

               playfx(FX_EXPLO);

               if (!invulnerable)
               {
                  // we hit the player, kill him!
                  --lives;
                  update_score();
                  invulnerable = 10;
               }
               
               continue;
            }

            sp1_MoveSprPix(sp_iter->s, &cr, sp_iter->sprite, 8 + sp_iter->x, 8 + sp_iter->y);
            break;

         case ST_ENEMY:

            if (!horde_delay)
            {
               if (!horde_iy)
                  sp_iter->x += horde_ix;
               else
                  sp_iter->y += horde_iy;

               // change frame
               sp_iter->frame = !sp_iter->frame;

               if (sp_iter->sprite == bomber)
               {
                  if (!sp_iter->delay--)
                  {
                     sp_iter->delay = 15 + rand() % 15;
                     add_bullet(ST_EBULLET, sp_iter->x + 4, sp_iter->y + 16);
                  }
               }
            }

            // player check
            if (!invulnerable && sp_iter->x < sprites[PLAYER].x + 16
                  && sprites[PLAYER].x < sp_iter->x + 16
                  && sp_iter->y < sprites[PLAYER].y + 16
                  && sprites[PLAYER].y < sp_iter->y + 16)
            {
               // convert into an explosion
               sp_iter->sprite = explosion;
               sp_iter->frame = 0;
               sp_iter->delay = 0;
               sp_iter->type = ST_EXPLO;

               // one less enemy
               --horde_count;

               playfx(FX_EXPLO);

               if (!invulnerable)
               {
                  // we hit the player, kill him!
                  --lives;
                  update_score();
                  invulnerable = 10;
               }
               
               continue;
            }

            // out of screen?
            if (sp_iter->y > HEIGHT)
            {
               // one less enemy
               --horde_count;

               // repeat the wave
               not_clean = 1;

               remove_sprite(sp_iter);
               // no drawing required
               break;
            }

            sp1_MoveSprPix(sp_iter->s, &cr, sp_iter->sprite + sp_iter->frame * 8 * 12, 8 + sp_iter->x, 8 + sp_iter->y);
            break;

         case ST_EXPLO:
            // first frame must be half frame longer
            if (sp_iter->delay < 2)
               sp_iter->delay++;
            else
            {
               sp_iter->delay = 1;
               sp_iter->frame++;
               if (sp_iter->frame == 3)
               {
                  // we're done!
                  remove_sprite(sp_iter);
                  break;
               }
            }
            
            sp1_MoveSprPix(sp_iter->s, &cr, sp_iter->sprite + sp_iter->frame * 8 * 12 , 8 + sp_iter->x, 8 + sp_iter->y);
            break;

         case ST_HIT:
            // first frame must be half frame longer
            if (sp_iter->delay < 2)
               sp_iter->delay++;
            else
            {
               sp_iter->delay = 0;
               sp_iter->frame++;
               if (sp_iter->frame == 2)
               {
                  // we're done!
                  remove_sprite(sp_iter);
                  break;
               }
            }
            sp1_MoveSprPix(sp_iter->s, &cr, sp_iter->sprite + sp_iter->frame * 4 * 8 , 8 + sp_iter->x, 8 + sp_iter->y);
            break;
      }
   }

   // update the lists
   collect_sprites();
}
void hit_task_fire_weapon(hitbox_t shooter, weapontype_t w){
	uint16_t start_x=0, start_y=0;
	bullet_t b;

	//Définit la position de départ selon l'emplacement du tireur
	if(w == BOMB){
		//Position en bas au milieu de l'invader qui tire
		start_x = shooter.x + shooter.width/2;
		start_y = shooter.y+shooter.height+1;
	}
	else{
		//Position en haut au milieu du vaisseau
		start_x = shooter.x + shooter.width/2;
		start_y = shooter.y-1;
	}

	//Tir de la bullet
	switch(w){
	case BOMB:
		b.weapon = &weapons[BOMB];
		b.hitbox.x = start_x-BOMB_WIDTH/2;
		b.hitbox.y = start_y;
		b.hitbox.width = BOMB_WIDTH;
		b.hitbox.height = BOMB_HEIGHT;
		b.hitbox.bitmap = (uint16_t *)bmp_bomb;
		break;
	case GUN:
		b.weapon = &weapons[GUN];
		b.hitbox.x = start_x-GUN_WIDTH/2;
		b.hitbox.y = start_y-GUN_HEIGHT;
		b.hitbox.width = GUN_WIDTH;
		b.hitbox.height = GUN_HEIGHT;
		b.hitbox.bitmap = (uint16_t *)bmp_gun;
		break;
	case RAIL:
		b.weapon = &weapons[RAIL];
		b.hitbox.x = start_x-RAIL_WIDTH/2;
		b.hitbox.y = GAME_ZONE_Y_MIN;
		b.hitbox.width = RAIL_WIDTH;
		b.hitbox.height = start_y - GAME_ZONE_Y_MIN;
		b.hitbox.bitmap = (uint16_t *)bmp_rail;
		break;
	case ROCKET:
		b.weapon = &weapons[ROCKET];
		b.hitbox.x = start_x-ROCKET_WIDTH/2;
		b.hitbox.y = start_y-ROCKET_HEIGHT;
		b.hitbox.width = ROCKET_WIDTH;
		b.hitbox.height = ROCKET_HEIGHT;
		b.hitbox.bitmap = (uint16_t *)bmp_rocket;
		break;
	case WAVE:
		b.weapon = &weapons[WAVE];
		b.hitbox.x = 0;
		b.hitbox.y = start_y-WAVE_HEIGHT;
		b.hitbox.width = WAVE_WIDTH;
		b.hitbox.height = WAVE_HEIGHT;
		b.hitbox.bitmap = (uint16_t *)bmp_wave;
		break;
	}

	//ajoute la bullet à la liste des bullets en jeu
	add_bullet(b);

}//fire_weapon()
Beispiel #8
0
void update_explorer(Explorer& obj)
{
	char i, vx, vy;
	short wx, wy, ww, wh;
	short nvx, nvy;
	
	// Game over if button pressed while dead
	if(!obj.active) {
		if((B_PRESSED || A_PRESSED) && !quitGame) {
			doGameOver();
		}
		return;
	}
	
	// Add health from rolling health
	if(rollingHealth > 0) {
		rollingHealth -= 10;
		obj.health += 10;
		if(obj.health > 1000) {
			obj.health = 1000;
			rollingHealth = 0;
		}
	}
	
	// Decrease health
	if(obj.nextHealthDecrease <= 0) {
		obj.nextHealthDecrease = 5;
		damage_explorer(obj, 1);
	}
	obj.nextHealthDecrease--;
	
	// Update animation
	if(LEFT_DOWN || RIGHT_DOWN || UP_DOWN || DOWN_DOWN) {
		obj.frameTime ++;
		if(obj.frameTime > 8) {
			obj.frame = !obj.frame;
			obj.frameTime = 0;
		}
	} else {
	// If facing left or right, set sprite to standing
		if(obj.direction == FACE_LEFT || obj.direction == FACE_RIGHT)
			obj.frame = true;
	}
	
	// Get horizontal velocity
	if(RIGHT_DOWN) {
		vx = 1;
		obj.direction = FACE_RIGHT;
	} else if(LEFT_DOWN) {
		vx = -1;
		obj.direction = FACE_LEFT;
	} else {
		vx = 0;
	}
	
	// Update horizontal position
	obj.x += vx;
	obj.x = (obj.x + 8 > gamew) ? gamew - 8 : obj.x;
	obj.x = (obj.x < 0) ? 0 : obj.x;
	
	// WALL COLLISION
	for(i = 0; i<numWalls; ++i) {
		if(!walls[i].active) continue;
		wx = walls[i].x*8;
		wy = walls[i].y*8;
		ww = walls[i].w*8;
		wh = walls[i].h*8;
		collideSpriteWall(obj.x, obj.y, true, vx, wx, wy, ww, wh);
	}
	// SPAWNER COLLISION
	for(i = 0; i<numSpawners; ++i) {
		if(!spawners[i].active) continue;
		wx = spawners[i].x*8;
		wy = spawners[i].y*8;
		collideSpriteSprite(obj.x, obj.y, true, vx, wx, wy);
	}
	
	// BADGUY COLLISION
	for(i = 0; i<numBadguys; ++i) {
		if(!badguys[i].active) continue;
		wx = badguys[i].x;
		wy = badguys[i].y;
		if(collideSpriteSprite(obj.x, obj.y, true, vx, wx, wy))
		{
			damage_explorer(p1, 1);
		}
	}
	
	// Get vertical velocity
	if(DOWN_DOWN) {
		vy = 1;
		obj.direction = FACE_DOWN;
	} else if(UP_DOWN) {
		vy = -1;
		obj.direction = FACE_UP;
	} else {
		vy = 0;
	}
	
	// Update vertical position
	obj.y += vy;
	obj.y = (obj.y + 8 > gameh) ? gameh - 8 : obj.y;
	obj.y = (obj.y < 0) ? 0 : obj.y;
	
	// WALL COLLISION
	for(i = 0; i<numWalls; ++i) {
		if(!walls[i].active) continue;
		wx = walls[i].x*8;
		wy = walls[i].y*8;
		ww = walls[i].w*8;
		wh = walls[i].h*8;
		collideSpriteWall(obj.x, obj.y, false, vy, wx, wy, ww, wh);
	}
	
	// SPAWNER COLLISION
	for(i = 0; i<numSpawners; ++i) {
		if(!spawners[i].active) continue;
		wx = spawners[i].x*8;
		wy = spawners[i].y*8;
		collideSpriteSprite(obj.x, obj.y, false, vy, wx, wy);
	}
	
	// BADGUY COLLISION
	for(i = 0; i<numBadguys; ++i) {
		if(!badguys[i].active) continue;
		wx = badguys[i].x;
		wy = badguys[i].y;
		if(collideSpriteSprite(obj.x, obj.y, false, vy, wx, wy))
		{
			damage_explorer(p1, 1);
		}
	}
	
	// KEY COLLISION
	for(i = 0; i<numKeys; ++i) {
		if(!keys[i].active) continue;
		wx = keys[i].x * 8;
		wy = keys[i].y * 8;
		if(intersectSpriteSprite(obj.x, obj.y, wx, wy))
		{
			activate_key(keys[i]);
		}
	}
	
	// EXIT COLLISION
	for(i = 0; i<numExits; ++i) {
		if(!exits[i].active) continue;
		wx = exits[i].x * 8;
		wy = exits[i].y * 8;
		if(intersectSpriteSprite(obj.x, obj.y, wx, wy))
		{
			activate_exit(exits[i]);
		}
	}
	
	// TREASURE COLLISION
	for(i = 0; i<numTreasures; ++i) {
		if(!treasures[i].active) continue;
		wx = treasures[i].x * 8;
		wy = treasures[i].y * 8;
		if(intersectSpriteSprite(obj.x, obj.y, wx, wy))
		{
			activate_treasure(treasures[i]);
		}
	}
	
	// Player shooting
	if(A_PRESSED) {
		autoFireTime = 8;
		nvx = (obj.direction == FACE_LEFT || LEFT_DOWN) ? -2 : 0;
		nvx = (obj.direction == FACE_RIGHT || RIGHT_DOWN) ? 2 : nvx;
		nvy = (obj.direction == FACE_UP || UP_DOWN) ? -2 : 0;
		nvy = (obj.direction == FACE_DOWN || DOWN_DOWN) ? 2 : nvy;
		
		add_bullet(obj.x+3, obj.y+3, nvx+vx, nvy+vy);
	}
	
	// Update Camera
	scrollx = 64 - obj.x;
	scrolly = 32 - obj.y;
}