예제 #1
0
void scene::scene_box_update(void)
{ 
  scene_box.set();
  
  OBJECT_HIERARCHY_ITERATOR it = render_hierarchy_next_new();
  SCENE_OBJECT_GEOMETRY *p_obj;
  int objnum = 0;
  while((p_obj = (SCENE_OBJECT_GEOMETRY *)render_hierarchy_next(&it))) {
    if(p_obj->object_is_geometry()) {
      BOX *p_box = p_obj->object_box_global_get();
      if(p_box) {   
        AABB tmp(p_box);
        scene_box.adjust(&tmp);
        objnum++;
      }
    }
  }
  
  if(!objnum) {
    scene_box.adjust(VECT(-DEFAULT_SCENE_BOX_SIZE,
                          -DEFAULT_SCENE_BOX_SIZE,
                          -DEFAULT_SCENE_BOX_SIZE));
    scene_box.adjust(VECT(DEFAULT_SCENE_BOX_SIZE, 
                          DEFAULT_SCENE_BOX_SIZE,
                          DEFAULT_SCENE_BOX_SIZE));
  }
}
예제 #2
0
파일: Player.cpp 프로젝트: yohokuno/suzuri
int CSurasuta::StepFrame(VECT pos,int state)
{
	VECT vect;
	m_anmtime++;
	if(m_state != state)
		m_anmtime = 0;
	switch(state)
	{
	case 0://normal
		m_posGun.Goto(m_playerpos[m_index] + c_gun_pos + VECT(0,sin(3.14*2*50*m_anmtime) * 2),SURASUTA_VEL);
		m_pimg->Draw2(110, m_posGun, 0, 1);	//武器
		m_posSurasuta.Goto(m_playerpos[m_index] + c_surasuta_pos + VECT(0,sin(3.14*2*50*(m_anmtime-20)) * 2),SURASUTA_VEL);
		m_pimg->Draw2(120, m_posSurasuta, 0, 0);		//スラスタ
		break;
	case 1://suikomi
		m_posGun.Goto(m_playerpos[m_index] + c_gun_pos + VECT(0,sin(3.14*2*50*m_anmtime) * 2),SURASUTA_VEL);
		m_pimg->Draw2(110, m_posGun, 0, 1);	//武器
		m_posSurasuta.Goto(m_playerpos[m_index] + c_suikomi_pos+ VECT(0,sin(3.14*2*50*(m_anmtime-20)) * 2),SURASUTA_VEL);
		m_pimg->Draw2(120, m_posSurasuta, 0, 0);		//スラスタ
		break;
	case 2://shot
		m_posSurasuta.Goto(m_playerpos[m_index] + c_gattai_pos + VECT(0,sin(3.14*2*50*(m_anmtime-20) * 2)),SURASUTA_VEL);
		m_posGun.Goto(m_playerpos[m_index] + c_gattai_pos + VECT(0,sin(3.14*2*50*m_anmtime)*2),SURASUTA_VEL);
		m_pimg->Draw2(110, m_posGun, 0, 3);//合体
		break;
	case 3://suikomi+shot
		m_posSurasuta.Goto(m_playerpos[m_index] + c_suikomi_pos+ VECT(0,sin(3.14*2*50*(m_anmtime-20)) * 2),SURASUTA_VEL);
		m_posGun.Goto(m_playerpos[m_index] + c_gattai_pos+ VECT(0,sin(3.14*2*50*m_anmtime) * 2),SURASUTA_VEL);
		m_pimg->Draw2(110, m_posSurasuta, 0, 0);//スラスタ
		m_pimg->Draw2(110, m_posGun, 0, 2);//ショット
		break;
	case 4://apear
		m_posSurasuta = pos+c_surasuta_pos;
		m_posGun = pos+c_gun_pos;
		m_pimg->Draw2(120, m_posSurasuta,  0, 0);		//スラスタ
		m_pimg->Draw2(120, m_posGun, 0, 1);		//スラスタ
		break;
	}
	//吸い込み効果音
	if((state==1 || state==3) && (m_state!=1 && m_state !=3))//開始
		g_pResource->sndSuikomi.Play(DSBPLAY_LOOPING );
	if((state!=1 && state!=3) && (m_state==1 || m_state==3))//停止
		g_pResource->sndSuikomi.Stop();
	m_state = state;
	//吸い込みエフェクト描画
	if(state==1||state==3)
	{
		g_pResource->imgSuikomi.Draw2(200,
			m_posSurasuta.x+m_pimg->GetWidth(),
			m_posSurasuta.y+m_pimg->GetHeight()/2-g_pResource->imgSuikomi.GetHeight()/2,
			m_anmtime/5%8,0);
	}
	//スラスタの遅れ処理
	m_playerpos[m_index] = pos;
	m_index++;
	if(m_index==SURASUTA_LATE)
		m_index=0;
	return 1;
}
예제 #3
0
void rtc_init(void)
{
	/* For detailed description please refer to hardware manual */
	SYSTEM.SUBOSCCR.BIT.SUBSTOP = 0;                         /* Enable SubClock circuit */

	RTC.RCR2.BIT.START      = 0;
	while (0 != RTC.RCR2.BIT.START);
	RTC.RCR2.BIT.RESET      = 1;
	while (1 == RTC.RCR2.BIT.RESET);
	/* Set initial time and date */
	RTC.RSECCNT.BYTE        = 0;
	RTC.RMINCNT.BYTE        = 0;
	RTC.RHRCNT.BYTE         = 0;
	RTC.RDAYCNT.BYTE        = 0;
	RTC.RWKCNT.BYTE         = 0;
	RTC.RMONCNT.BYTE        = 0;
	RTC.RYRCNT.WORD         = 0x2000;
	/* Set periodic interrupt */
	RTC.RCR1.BYTE           = 0;
	RTC.RCR1.BIT.PES        = 1;                             /* Set periodic interrupts frequency to 256 Hz */
	RTC.RCR1.BIT.PIE        = 1;                             /* Enable periodic interrupts */
	_isr_vectors[VECT(RTC,PRD)] = rtc_irq_handler;
	IR(RTC,PRD)             = 0;                             /* Clear interrupt flag */
	IPR(RTC,PRD)            = 15;                            /* Set priority level */
	IEN(RTC,PRD)            = 1;                             /* Enable interrupt in ICU */
	RTC.RCR2.BIT.START      = 1;                             /* Start RTC */
	while (1 != RTC.RCR2.BIT.START);
}
예제 #4
0
CEnemyShot::CEnemyShot(CNkImage* pimg,VECT pos,VECT vel,int anm)
{
	m_pimg=pimg;
	SetCenter(pos);
	m_vel=vel;
	m_velOrg=vel;
	m_pul=VECT(0,0);
	m_anm=anm;
};
예제 #5
0
파일: Player.cpp 프로젝트: yohokuno/suzuri
int CPlayer::CollTikei()
{
	return
		g_pStage->CollTikei(VECT(GetLeft()+PL_OFFSET,GetTop()+PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetLeft()+PL_OFFSET,GetBottom()-PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetRight()-PL_OFFSET,GetTop()+PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetRight()-PL_OFFSET,GetBottom()-PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetLeft()+GetWidth()/2,GetTop()))||
		g_pStage->CollTikei(VECT(GetLeft()+GetWidth()/2,GetBottom()))||
		g_pStage->CollTikei(VECT(GetLeft(),GetTop()+GetHeight()/2))||
		g_pStage->CollTikei(VECT(GetRight(),GetTop()+GetHeight()/2));
}
예제 #6
0
파일: Player.cpp 프로젝트: yohokuno/suzuri
CPlayer::CPlayer(CNkImage* pimg, CNkImage* pimgSurasuta, int zanki,int item):m_surasuta(pimgSurasuta,VECT(-40,105))
{
	m_pimg = pimg;
	m_zanki = zanki;
	m_pos = VECT(-40,105);
	m_shottime = 0;
	m_anmtime = 0;
	m_state = 1;	//出現アニメーションする、ということ。
	m_muteki = PLAYER_MUTEKI;
	m_item = 0;
	m_power = 0;
	for(m_item=0;m_item<=item;++m_item)
		if(m_item%(80+150*m_power) == 0 && m_power<10)
			m_power++;
}
예제 #7
0
//-----------------------------------------------------------------------------
// Construction/Destruction
//-----------------------------------------------------------------------------
CVertex::CVertex()
{
    TRACE_ENTER_FN( CVertex::CVertex )

    m_eClassType = VERTEXCLASS;
    m_vColor = m_vPos = VECT( 0, 0, 0 );
    m_fU = m_fV = m_fVirtX = m_fVirtY = m_fVirtZ = 0.0f;
    m_fPrecision = 0.1f;

    m_pConnectedVerts = NULL;
    m_iNumConnectedVerts = 0;

    sprintf( m_strName, "Vertex:%d", m_UniqueID );
    m_UniqueID++;

    TRACE_LEAVE_FN()
}
예제 #8
0
bool Triangle::checkPoint(const Point& point) const
{
    Point ca = VECT(points[0], points[1]);
    Point cd = VECT(points[0], point);
    Point ab = VECT(points[1], points[2]);
    Point ad = VECT(points[1], point);
    Point bc = VECT(points[2], points[0]);
    Point bd = VECT(points[2], point);

    int mul1 = MUL(ca, cd);
    int mul2 = MUL(ab, ad);
    int mul3 = MUL(bc, bd);

    return ((SGN(mul1) == SGN(mul2)) &&
            (SGN(mul2) == SGN(mul3)) &&
            (SGN(mul3) == SGN(mul1)));
}
예제 #9
0
파일: Player.cpp 프로젝트: yohokuno/suzuri
int CPlayer::StepFrame()
{
	int i;
	VECT former = m_pos;
	switch(m_state)
	{
	case 0://通常状態
		//移動処理
		if(GetInputState(INP_RIGHT) && GetRight() < SCREEN_WIDTH)
			m_pos.x += PLAYER_SPEED;
		while(CollTikei())
		{
			m_pos.x --;
			if(m_pos.x < 0 && m_muteki==0)
			{
				Damage();
				break;
			}
		}
		if(GetInputState(INP_LEFT) && GetLeft() > 0)
			m_pos.x -= PLAYER_SPEED;
		if(CollTikei())
			m_pos.x = former.x;
		if(GetInputState(INP_DOWN) && GetBottom() < SCREEN_HEIGHT)
			m_pos.y += PLAYER_SPEED;
		if(GetInputState(INP_UP) && GetTop() > 0)
			m_pos.y -= PLAYER_SPEED;
		if(CollTikei())
			m_pos.y = former.y;
		//ショット
		if(GetInputState(INP_B0))
		{
			m_shottime++;
			if(m_shottime%(8-m_power/2) == 0)
			{
				g_pResource->sndShot.Play(0);
				g_pshot.Add(new CPlayerShot(&g_pResource->imgPlayerShot, m_surasuta.GetPos()-VECT(10,5), VECT(20,0)));
				g_pshot.Add(new CPlayerShot(&g_pResource->imgPlayerShot, m_surasuta.GetPos()+VECT(-10,5), VECT(20,0)));
			}
			if(m_shottime%(10) == 0)
			{
				if(m_power>0)
				{
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot2, GetCenter()+VECT(0,5), VECT(10,3)));
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot1, GetCenter()-VECT(0,5), VECT(10,-3)));
				}
				if(m_power>3)
				{
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot2, GetCenter()+VECT(0,5), VECT(10,1.5)));
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot1, GetCenter()-VECT(0,5), VECT(10,-1.5)));
				}
				if(m_power>5)
				{
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot2, GetCenter()+VECT(0,5), VECT(10,7)));
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot1, GetCenter()-VECT(0,5), VECT(10,-7)));
				}
				if(m_power>7)
				{
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot2, GetCenter()+VECT(0,5), VECT(10,5)));
					g_pshot.Add(new CPlayerShot(&g_pResource->imgSubShot1, GetCenter()-VECT(0,5), VECT(10,-5)));
				}
			}
		}
		//無敵処理
		if(m_muteki>0)
			m_muteki--;
		//吸い込み
		if(GetInputState(INP_B1))
		{
			for(i=0; i<ITEM_NUM; ++i)
				if(g_item[i])
					g_item[i]->Pull();
			for(i=0; i<ENEMYSHOT_NUM; ++i)
				if(g_enemyShot[i])
					g_enemyShot[i]->Pull(GetCenter());
		}
		//当たり判定:アイテム
		if(m_anmtime%2)
		for(i=0; i<ITEM_NUM; ++i){
			if(g_item[i]){
				if(this->IsColl(g_item[i])){
					g_pResource->sndItem.Play(0);
					g_pScore->item ++;
					g_pScore->score += SCORE_ITEM;
					m_item++;
					if(m_item%(80+150*m_power) == 0 && m_power<10)
						m_power++;
					SAFE_DELETE(g_item[i]);
					break;
				}
			}
		}
		//当たり判定:敵
		if(m_muteki==0){
			for(i=0; i<ENEMY_NUM; ++i){
				if(g_enemy[i]&&g_enemy[i]->GetHP()!=20){
					if(this->IsColl2(g_enemy[i])){
						Damage();
						break;
					}
				}
			}
		}
		//当たり判定:敵弾
		if(m_muteki==0){
			for(i=0; i<ENEMYSHOT_NUM; ++i){
				if(g_enemyShot[i]){
					if(this->IsColl2(g_enemyShot[i])){
						Damage();
						break;
					}
				}
			}
		}
		//アニメ処理
		m_anmtime++;
		if(m_anmtime==PLAYER_ANMCYCLE)
			m_anmtime=0;
		//描画
		//本体(無敵でない・無敵中点滅オン・ポーズ寸前)
		if(m_muteki==0||m_anmtime%5||GetInputEvent(INP_B3))
			m_pimg->Draw2(100, m_pos.x, m_pos.y, m_anmtime*3/PLAYER_ANMCYCLE, GetInputState(INP_LEFT));
		//スラスタ
		if(GetInputState(INP_B0) && GetInputState(INP_B1))	//吸い込み+ショット
			m_surasuta.StepFrame(m_pos,3);
		else if(GetInputState(INP_B0))//ショット(変形
			m_surasuta.StepFrame(m_pos,2);
		else if(GetInputState(INP_B1))//吸い込み
			m_surasuta.StepFrame(m_pos,1);
		else//なんもなし
			m_surasuta.StepFrame(m_pos,0);
		break;
	case 1://出現モーション中
		m_anmtime++;
		m_pos.x += (30.0-m_anmtime)/5;
		m_pimg->Draw2(100, m_pos);					//本体
		m_surasuta.StepFrame(m_pos,4);
		if(m_anmtime > 40)
		{
			m_anmtime = 0;
			m_muteki = PLAYER_MUTEKI;
			m_state = 0;//通常状態に戻す
		}
		break;
	case 2://死亡モーション(墜落)中
		m_anmtime++;
		m_pos.y += (double)m_anmtime/5;
		m_pimg->Draw2(100, m_pos, 0, 2);
		m_surasuta.StepFrame(m_pos,4);
		if(m_anmtime > 40)
		{
			//ゲームオーバーチェックは墜落が終わってから
			if(m_zanki<0)
				return 0;
			m_pos = VECT(-40,105);
			m_anmtime = 0;
			m_state = 1;
		}
		break;
	}
	//残機数描画
	for(i=0;i<m_zanki;++i)
		g_pResource->imgZanki.Draw2(70,130+i*20,215);
	return 1;
}
예제 #10
0
파일: Player.cpp 프로젝트: yohokuno/suzuri
int CPlayer::CollTikei()
{
	return
		g_pStage->CollTikei(VECT(GetLeft()+PL_OFFSET,GetTop()+PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetLeft()+PL_OFFSET,GetBottom()-PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetRight()-PL_OFFSET,GetTop()+PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetRight()-PL_OFFSET,GetBottom()-PL_OFFSET))||
		g_pStage->CollTikei(VECT(GetLeft()+GetWidth()/2,GetTop()))||
		g_pStage->CollTikei(VECT(GetLeft()+GetWidth()/2,GetBottom()))||
		g_pStage->CollTikei(VECT(GetLeft(),GetTop()+GetHeight()/2))||
		g_pStage->CollTikei(VECT(GetRight(),GetTop()+GetHeight()/2));
}
/*-----------------------------------------------------------------------------
	スラスタ関係
-----------------------------------------------------------------------------*/
const VECT c_surasuta_pos = VECT( 8, 15);
const VECT c_gun_pos = VECT( 4, 20);
const VECT c_gattai_pos = VECT( 15, 20);
const VECT c_suikomi_pos = VECT(20,15);
#define SURASUTA_VEL 5
int CSurasuta::StepFrame(VECT pos,int state)
{
	VECT vect;
	m_anmtime++;
	if(m_state != state)
		m_anmtime = 0;
	switch(state)
	{
	case 0://normal
		m_posGun.Goto(m_playerpos[m_index] + c_gun_pos + VECT(0,sin(3.14*2*50*m_anmtime) * 2),SURASUTA_VEL);
		m_pimg->Draw2(110, m_posGun, 0, 1);	//武器
예제 #11
0
// Helper function for the lightning effect.
// Creates an recursive lightning bolt
void light_bolt(VECT pos1, VECT pos2, int points, float noise, float thickness, int level, float color[4]) {
	if(level > 6)
		return;			// Don't recurse too deeply

	// Create the points array
	VECT *point = new VECT[points];
	if(!point)
		return;

	// Define the end points
	point[0] = pos1;
	point[points-1] = pos2;

	// Compute the direction from pos1 to pos2
	VECT dir = pos2 - pos1;
	float dist = vector_length(dir);
	float step = dist / points;
	normalize(dir);

	// Make a straight line between pos1 and pos2, and randomize it a bit
	for(int f=1; f < points-1; f++) {
		point[f] = point[f-1] + step * dir;

		point[f].x += RANDF(-noise, noise);
		point[f].y += RANDF(-noise, noise);
		point[f].z += RANDF(-noise, noise);

		// Create some recursive bolts
		if(RAND(0,100) > 45) {
			// Choose a destination which isn't too close to the original point
			VECT dest;
			dest.x = RANDF(-noise,noise);
			dest.y = RANDF(-noise,noise);
			dest.z = RANDF(-noise,noise);
			bool ok = false;
			while(!ok) {
				float bdist = vector_length(VECT(dest - point[f]));
				float rad = noise * 0.5f;
				if(bdist > rad) {
					// Also try to steer the bolts towards the ground
					if((point[f].y + dest.y) < point[f].y)
						ok = true;
					else
						ok = false;
				}
				if(!ok) {
					dest.x = RANDF(-noise,noise);
					dest.y = RANDF(-noise,noise);
					dest.z = RANDF(-noise,noise);
				}
			}

			dest *= RANDF(3.0f, 7.0f);
			light_bolt(point[f], point[f] + dest, int(points * 0.65f), noise * 0.5f, thickness * 0.5f, level + 1, color);
		}
	}

	glColor4fv(color);
	glLineWidth(thickness);
	glBegin(GL_LINE_STRIP);
	for(int f=0; f<points; f++) {
	//for(int f=0; f<points-1; f++) {
		glVertex3f(point[f].x, point[f].y, point[f].z);
		//glVertex3f(point[f+1].x, point[f+1].y, point[f+1].z);
	}
	glEnd();

	// Draw some glows
	if(level == 0) {
		BIND_TEXTURE(part_glow);
		glColor4f(.4f, .8f, 1, RANDF(.15f,.25f));
		for(int f=0; f<points; f++) {
			glPushMatrix();
			glTranslatef(point[f].x, point[f].y, point[f].z);
			// Negate the camera rotation
			glRotatef(45.0f, 0,1,0);
			glRotatef(-30.0f, 1,0,0);
			glBegin(GL_TRIANGLE_STRIP);
				glTexCoord2f(1,1); glVertex3f( 1,  1,  1);
				glTexCoord2f(0,1); glVertex3f(-1,  1,  1);
				glTexCoord2f(1,0); glVertex3f( 1, -1, -1);
				glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
			glEnd();
			glPopMatrix();
		}
		BIND_TEXTURE(0);
	}

	delete [] point;
}
예제 #12
0
// Move the player
void PLAYER::move() {
#ifndef EDITOR
	int who = (this == &p1) ? 1 : 2;
	int who2 = who-1; 	// Used for array indices

	// Reduce the icon alpha
	if(p_icon_alpha[who2]) {
		p_icon_alpha[who2] -= 0.005f;
		if(p_icon_alpha[who2] < 0.0f)
			p_icon_alpha[who2] = 0.0f;
	}

	// If we're dead, reduce the death counter and respawn
	if(!alive) {
		death_counter--;
		if(death_counter == 0) {
			// Respawn to a block
			int ox, oy;
			get_respawn_position((int)get_real_x(), (int)get_real_y(), ox, oy);

			int odir = dir;
			//clear();
			alive = true;
			x = ox;
			y = oy;
			dir = odir;
			nextdir = dir;
			tx = x;
			ty = y;
			walking = false;
			jumping = false;
			dying = false;
			offset = 0.0f;
			create_teleport_effect(x, y);
			show_icon(who2);

			// Play the appear sound
			play_sound(SND_APPEAR, false);

		}
		return;
	}

	// Advance the dying animation if we're actually dying
	if(dying) {
		die_anim -= 0.03f;

		// Create the blue "burning down" effect
		float px = get_real_x();
		float py = get_real_y();
		for(int f=0; f < RAND(2,10); f++) {
			float rnd = RANDF(-0.3f, 0.3f);
			VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py);
			pos.x += rnd;
			pos.z -= rnd;
			if(pos.y < 0.0f)
				pos.y = 0.0f;
			VECT dir = 0.0f;
			float c1[4] = { 0.1f, 0.7f, 1, 1 };
			float c2[4] = { 0.1f, 0.7f, 1, 0 };
			add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star);
		}

		if(die_anim < 0.0f) {
			die_anim = 0.0f;
			alive = false;

			// Explode the player bombs
			if(num_bombs > 0) {
				list<BOMB>::iterator b;
				for(b = bomblist.begin(); b != bomblist.end(); ++b)
					if((*b).owner == who && (*b).time > 1)
						(*b).time = 1;		// Makes the bomb explode on the next cycle
			}
		}

		return;
	}


	// Jumping stuff
	if(jumping) {
		jump_pos += jump_speed;
		if(jump_pos >= 1.0f) {
			jump_pos = 1.0f;

			// We're now on the target tile
			x = jump_tx;
			y = jump_ty;
			tx = x;
			ty = y;
			offset = 0.0f;
			jumping = false;
		}

		// Create some particles if we're teleporting
		if(in_teleport && jumping) {
			VECT pos(get_real_x(), 0.25f, get_real_y());
			pos += jump_dir * jump_pos * jump_dist;
			pos.y += jump_height * SIN(180.0f * jump_pos);

			VECT dir;
			for(int f=0; f<5; f++) {
				VECT ppos = pos + VECT(RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f));
				dir.x = dir.y = dir.z = 0.0f;
				float c1[4] = { 0.3, 0.7f, 1, 1 };
				float c2[4] = { 0, 0, 1, 0 };

				add_particle(ppos, dir, RAND(10,30), 0.1f, 0.3f, c1, c2, part_teleport);
			}
		}


		// This is a dirty hack. Read the comments from the beginning of this file.
		if(map[jump_tx][jump_ty][1] && jump_pos > 0.9f) {
			players_on_block_x[who2] = jump_tx;
			players_on_block_y[who2] = jump_ty;
		}

		return;
	}

	// This is a dirty hack. Read the comments from the beginning of this file.
	if(map[x][y][1]) {
		players_on_block_x[who2] = x;
		players_on_block_y[who2] = y;
		//return;
	}
	else {
		players_on_block_x[who2] = -1;
	}

	// Don't move if we're using the napalm or the teleport power
	if(using_special_power && (which_special_power == RED_POWER_NAPALM))
		return;
	if(using_special_power == who && (which_special_power == BLUE_POWER_TELEPORT))
		return;

	// Don't move if the level is finished
	if(level_pause)
		return;


	// Advance the animation
	anim += 0.20f;
	if((int)anim > 3)
		anim = 0.0f;

	// Advance the turning animation
	if(turning) {
		turning_counter++;
		if(turning_counter == 5) {
			dir = nextdir;
			nextdir = dir + 1;
			if(nextdir > DIR_W)
				nextdir = DIR_N;
		}
		else if(turning_counter == 10) {
			dir = nextdir;
			turning = false;
		}
	}


	if(!walking && ((config.moving_style[who2] == MOV_RELATIVE && !key[config.key_up[who2]]) || (config.moving_style[who2] == MOV_ABSOLUTE && !key[config.key_up[who2]] && !key[config.key_down[who2]] && !key[config.key_left[who2]] && !key[config.key_right[who2]])))
		anim = 0.0f;

	// Check if we're on a block
	bool on_block = false;
	if(map_solid(x,y))
		on_block = true;

	// Don't move if we're using the flower power (absolute)
	if(on_block && config.moving_style[who2] == MOV_ABSOLUTE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0))
		return;


	// Check for turning input
	if(key[config.key_left[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[0] && !turning) {
				// Turn left
				nextdir = dir - 1;
				if(nextdir < DIR_N)
					nextdir = DIR_W;

				if(!walking)
					dir = nextdir;

				turn_key_down[0] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_W;
			walking = true;
			offset = 0.0f;

			tx = x - 1;
			ty = y;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[0] = false;

	if(key[config.key_right[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[1] && !turning) {
				// Turn right
				nextdir = dir + 1;
				if(nextdir > DIR_W)
					nextdir = DIR_N;

				if(!walking)
					dir = nextdir;

				turn_key_down[1] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_E;
			walking = true;
			offset = 0.0f;

			tx = x + 1;
			ty = y;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[1] = false;

	// Check for 180 degree turning
	if(key[config.key_down[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[2] && !turning && !walking && !key[config.key_up[who2]]) {
				nextdir = dir + 1;
				if(nextdir > DIR_W)
					nextdir = DIR_N;
				turning = true;
				turning_counter = 0;

				turn_key_down[2] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_S;
			walking = true;
			offset = 0.0f;

			tx = x;
			ty = y + 1;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[2] = false;

	// Don't move if we're using the flower power (relative)
	if(on_block && config.moving_style[who2] == MOV_RELATIVE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0))
		return;

	// Check for walking input
	if(key[config.key_up[who2]] && !walking && !turning) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			walking = true;
			offset = 0.0f;

			dir = nextdir;

			switch(dir) {
				default:
				case DIR_N: tx = x; ty = y - 1; break;
				case DIR_E: tx = x + 1; ty = y; break;
				case DIR_S: tx = x; ty = y + 1; break;
				case DIR_W: tx = x - 1; ty = y; break;
			}

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
		else {
			// Absolute moving
			dir = DIR_N;
			walking = true;
			offset = 0.0f;

			tx = x;
			ty = y - 1;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}


	// Move towards the target tile
	if(offset < 1.0f && (tx != x || ty != y)) {
		offset += 0.1f;

		// If we're reached the target tile, move again
		if(offset >= 1.0f) {
			x = tx;
			y = ty;
			offset = 0.0f;
			walking = false;

			in_teleport = 0;
		}
	}

	// Reload the weapons
	if(reload > 0)
		reload--;

	// Dropping bombs
	if(key[config.key_shoot[who2]] && reload == 0 && num_bombs < 3 && !on_block && !icon_menu.wait) {
		reload = 30;

		// Plant the bomb
		add_bomb(x, y, BTYP_NORMAL, who);
		num_bombs++;

		// Play the sound
		play_sound(SND_BOMB, false);
	}


	// Invoke the special powers
	if(key[config.key_special[who2]]) {
		open_icon_menu(who, on_block);
		show_icon(0);
		show_icon(1);
	}

#endif
}