⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cracecar.cpp

📁 Visual C++ 游戏开发与设计实例 源代码(所有)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// RACE X
//
// Written by Mauricio Teichmann Ritter
//
// Copyright (C) 2002, Brazil. All rights reserved.
// 
//

#include "stdafx.h"
#include "RaceX.h"
#include "cRaceCar.h"
#include ".\applib\ckeyboard.h"
#include <math.h>
#include <stdio.h>
#include "cRaceTrack.h"



#define CARBOUND_POINTS 4

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


cRaceCar::cRaceCar()
{
	m_iMaxSpeed = 270;
	m_iSpeed = 0;
	m_fDirectionY = -9;
	m_fDirectionX = 0;
	m_fIncrementY = 1;
	m_fIncrementX = 1;

	m_fBackupIncrementX = 1;
	m_fBackupIncrementY = 1;
	m_iBackupDistanceToNextCheckPoint = 0;
	m_fBackupDirectionY = -9;
	m_fBackupDirectionX = 0;
	m_iBackupAngle = 0;


	m_iAngle = 0;

	m_iCheckPoint = -1;
	m_iLaps = 0;

	m_pBound = (POINT*) malloc(sizeof(POINT) * CARBOUND_POINTS);

	m_lLastTurn = 0;
	m_lLastSpeedIncr = 0;

	m_iCarState = CARSTATE_OK;

	POINT	tmpPoints[] = {	{12,4},  {26,4},  {26,29}, {12,29}};


	m_pBound =(POINT*)  memcpy((void*) m_pBound,(void*) &tmpPoints, sizeof(POINT)* CARBOUND_POINTS);
	
	m_hcRaceCar.CreatePolygonBound(m_pBound, CARBOUND_POINTS);
}

cRaceCar::~cRaceCar()
{
	free(m_pBound);
	m_hcRaceCar.Destroy();
}

void cRaceCar::SetPos(int iX, int iY)
{
	m_fPosX = (float)iX;
	m_fPosY = (float)iY;
}

void cRaceCar::Create(int iColor)
{
	m_sprCar.Create(GetMainApp()->m_hInst, iColor, 360, 160, RGB(0,0,0), 40, 40);
	m_hcRaceCar.CreateRectBound(40,40);
	iCrashTime = 0;

	m_iColor = iColor;

	m_pSound.Create(MAKEINTRESOURCE(IDR_ENGINE), DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY, DS3DALG_HRTF_LIGHT);
	m_pSound.m_pSoundBuffer->SetCurrentPosition( 0 );

	m_pCrashSound.Create(MAKEINTRESOURCE(IDR_EXPLODE), DSBCAPS_CTRL3D, DS3DALG_HRTF_LIGHT);
	m_pCrashSound.m_pSoundBuffer->SetCurrentPosition( 0 );

	m_lCurrentTime = 0;
	m_bRemoteKeyboardStatus = 0;

	m_bLastSent_Speed = -1;
	m_bLastSent_Position = -1;
	m_bLastSent_CarState = -1;
	m_bLastSent_Laps = -1;
	m_bLastSent_Angle = -1;
	m_dwLastSent_LastLapTime = -1;
	m_nLastSent_PosX = -1;
	m_nLastSent_PosY = -1;
}

void cRaceCar::Destroy()
{
	m_sprCar.Destroy();
	m_hcRaceCar.Destroy();
	m_sprCarExplode_0.Destroy();
	m_sprCarExplode_135.Destroy();
	m_sprCarExplode_180.Destroy();
	m_sprCarExplode_225.Destroy();
	m_sprCarExplode_270.Destroy();
	m_sprCarExplode_315.Destroy();
	m_sprCarExplode_45.Destroy();
	m_sprCarExplode_90.Destroy();
	m_pSound.Destroy();
	m_pCrashSound.Destroy();
}

void cRaceCar::Draw(int iViewX, int iViewY)
{
	// Draw the car based on the current position in the map
	int iClipX = 0, iClipY = 0;
	int iClipWidth = 40, iClipHeight = 40;
	int iX = (int)m_fPosX - iViewX;
	int iY = (int) m_fPosY - iViewY;

	if((int)m_fPosX - iViewX > 640)
		return;

	if((int)m_fPosX - iViewX + 40 < 0)
		return;

	if((int) m_fPosY - iViewY > 460)
		return;

	if((int) m_fPosY - iViewY +40 < 0)
		return;



	if((int) m_fPosY - iViewY + 40 > 460)
		iClipHeight = 40-((int) m_fPosY - iViewY + 40 - 460);

	if((int) m_fPosX - iViewX + 40 > 640)
		iClipWidth = 40-((int) m_fPosX - iViewX + 40 - 640);

	if((int)m_fPosX - iViewX < 0)
	{
		iClipX = abs((int)m_fPosX - iViewX);
		iClipWidth -= iClipX;
		iX = 0;
	}

	if((int)m_fPosY - iViewY < 0)
	{
		iClipY = abs((int)m_fPosY - iViewY);
		iClipHeight -= iClipY;
		iY = 0;
	}

	if(m_iCarState == CARSTATE_CRASHED_WALL)
	{
		// If we crashed, play the explosion sprite
		if(m_iAngle == 0)
			m_sprCarExplode_0.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_0.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle > 0 && m_iAngle < 90)
			m_sprCarExplode_45.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_45.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle == 90)
			m_sprCarExplode_90.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_90.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle > 90 && m_iAngle < 180)
			m_sprCarExplode_135.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_135.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle == 180)
			m_sprCarExplode_180.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_180.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle > 180 && m_iAngle < 270)
			m_sprCarExplode_225.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_225.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle == 270)
			m_sprCarExplode_270.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_270.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);

		if(m_iAngle > 270 && m_iAngle < 360)
			m_sprCarExplode_315.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_315.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
	}
	else
	{
		// otherwise, blit the normal car, in its current angle
		m_sprCar.Draw(GetMainApp()->m_pBackBuffer, iX, iY, FALSE, iClipX, iClipY, iClipWidth, iClipHeight);
	}

	// If you want to see the car bounding rect, uncomment this
	
	/*HDC hdc;
	GetMainApp()->m_pBackBuffer->GetDC(&hdc);
	OffsetRgn(m_hcRaceCar.hBoundingPoly, (int)m_fPosX - iViewX, (int) m_fPosY - iViewY);
	FillRgn(hdc, m_hcRaceCar.hBoundingPoly, (HBRUSH) GetStockObject(BLACK_BRUSH));
	OffsetRgn(m_hcRaceCar.hBoundingPoly, -1*((int)m_fPosX - iViewX), -1*((int) m_fPosY - iViewY));
	GetMainApp()->m_pBackBuffer->ReleaseDC(hdc);
	*/
}


void cRaceCar::Process(void* pTrack)
{
	#define SPEEDXTURN 70
	#define	TURN_TIME  45
	#define	RAISESPEED_TIME 85
	#define MAX_SPEED_FOR_CURVE 180
	#define MAX_SPEED_FOR_IDLE  200

	//升高速度量从而降低游戏速度
	//降低速度量从而使游戏更快速
	#define	_SPEED_FACTOR_ 17

	int iX, iY;
	static long lLastMessage;

	//iTurnCar = TURN_RIGHT;
	cRaceTrack*	theTrack = (cRaceTrack*)pTrack;
	cKeyboard	pKeyboard;

	//如果赛车不在正常状态
	if(m_iCarState != CARSTATE_OK)
	{
		//赛车发生碰撞,需要调入爆炸的声音
		if(iCrashTime == 0)
		{
			iCrashTime = GetTickCount();
			if(m_iCarState != CARSTATE_RACECOMPLETED)
				m_pCrashSound.Play();
		}
		//爆炸
		Crashed();
		if(m_iCarState == CARSTATE_RACECOMPLETED)
		{
		}
		else
		{
			if(GetTickCount() - iCrashTime > 2500)
			{

				// Crash time elapse, return the car to the backuped position
				m_sprCarExplode_0.Destroy();
				m_sprCarExplode_135.Destroy();
				m_sprCarExplode_180.Destroy();
				m_sprCarExplode_225.Destroy();
				m_sprCarExplode_270.Destroy();
				m_sprCarExplode_315.Destroy();
				m_sprCarExplode_45.Destroy();
				m_sprCarExplode_90.Destroy();

				if( (GetRaceXApp()->m_bIsMultiplayer == TRUE && GetRaceXApp()->GetMultiplayer()->IsHosting()) ||
					GetRaceXApp()->m_bIsMultiplayer == FALSE)
				{
					m_fDirectionX = m_fBackupDirectionX;
					m_fDirectionY = m_fBackupDirectionY;
					m_fIncrementX = m_fBackupIncrementX;
					m_fIncrementY = m_fBackupIncrementY;

					m_iDistanceToNextCheckPoint = m_iBackupDistanceToNextCheckPoint;
					iTurnCar = iBackupTurnCar;
					m_iAngle = m_iBackupAngle;
					m_fPosX = m_fBackupPosX;
					m_fPosY = m_fBackupPosY;
					m_sprCar.m_iAbsolutePosition = m_iBackupSprite;

					if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ2 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ0P3 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ0P2)
					{
						m_fPosY+=10;
					}

					if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ3||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P3 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P2)
					{
						m_fPosY-=10;
					}

					if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ0 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P1 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P2)
					{
						m_fPosX+=10;
					}

					if(theTrack->GetRoadType((int)m_fPosX+10,(int) m_fPosY+10) == ID_ROADTYPE_ROADQ1 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ3P1 ||
					   theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ3P2)
					{
						m_fPosX-=10;
					}

					RotateBound(m_iAngle);

					iX = 0;
					iY = 0;
					m_iDistanceToNextCheckPoint = 999999999;
					do
					{
						iX = iX / 40;
						iY = iY / 40;
						theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
						if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
						{
							m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
						}

						if(iX != -1)
							iX += 40;

					}while(iX>0);

					for(int i=0;i<theTrack->GetNumberOfCars();i++)
					{
						if(m_bID != theTrack->m_pRaceCars[i]->GetID())
						{
							int iSrcX, iSrcY;

							theTrack->m_pRaceCars[i]->GetPos(&iSrcX, &iSrcY);

							if(m_hcRaceCar.HaveHitted(&theTrack->m_pRaceCars[i]->m_hcRaceCar, m_fPosX, m_fPosY, iSrcX, iSrcY) == FALSE)
							{
								m_iCarState = CARSTATE_OK;
								iCrashTime = 0;
							}
						}
					}
				}
			}
		}
	}
	else
	{
		int i;
		iCrashTime = 0;
		
		//如果赛车由人控制,则读取键盘值,判断用户意图
		if(m_iControlType == CTRL_USER)
		{
			if(pKeyboard.CheckKey(DIK_RIGHT))
			{
				TurnCarRight();
			}

			if(pKeyboard.CheckKey(DIK_LEFT))
			{
				TurnCarLeft();
			}

			if(pKeyboard.CheckKey(DIK_DOWN))
			{
				BreakCar();
			}
			
			if(pKeyboard.CheckKey(DIK_UP))
			{
				Accelerate();
			}
			else
			{
				Idle();
			}
		}/*USER CONTROL*/

		

		//远端用户,发送键盘消息到主机
		if(m_iControlType == CTRL_NETWORK_REMOTE &&
			GetRaceXApp()->m_bIsMultiplayer == TRUE &&
			GetRaceXApp()->GetMultiplayer()->IsHosting() )
		{
			// 键盘状态是一个字节变量,设置某些位从而判断哪个键被按下
			if(m_bRemoteKeyboardStatus & 0x01)
			{
				TurnCarRight();
			}
			if(m_bRemoteKeyboardStatus & 0x02)
			{
				TurnCarLeft();
			}
			if(m_bRemoteKeyboardStatus & 0x04)
			{
				BreakCar();
			}
			if(m_bRemoteKeyboardStatus & 0x08)
			{
				Accelerate();
			}
			else
			{
				Idle();
			}
		}

		//电脑控制的赛车
		if(m_iControlType == CTRL_COMPUTER)
		{
			BOOL bCanBrake = FALSE;
			//如果当前地图中贴片的角度和当前赛车的行进角度不一样,则需调整赛车的行进角度
			if(m_iAngle != theTrack->GetAngle(m_fPosX+20, m_fPosY+20) &&
			   theTrack->GetAngle(m_fPosX+20, m_fPosY+20) != 370)
			{

				int iValue1 = (360-m_iAngle)+theTrack->GetAngle(m_fPosX+20, m_fPosY+20);
				if(iValue1 > 360)
				{
					iValue1 = iValue1 % 360;
				}

				int iValue2 = (m_iAngle-theTrack->GetAngle(m_fPosX+20, m_fPosY+20));
				if(iValue2 < 0)
				{
					iValue2+=360;
				}

				if(iValue1 < iValue2)
				{
					TurnCarRight();
					bCanBrake = TRUE;
				}
				else
				{
					TurnCarLeft();
					bCanBrake = TRUE;
				}
			}
			//如果速度过快,则刹车
			if(m_iSpeed > 270)
			{
				if(theTrack->CarHittedRoad(this, (int) m_fPosX+20+(m_iSpeed * (m_fDirectionX/9.0f)), (int) m_fPosY+20+ (m_iSpeed * (m_fDirectionY/9.0f))) == TRUE)
				BreakCar();
			}
			if(bCanBrake == TRUE)
			{
				for(i=m_iSpeed-30;i>=0;i-=40)
				{
					if(theTrack->CarHittedRoad(this,(int)m_fPosX+20+(i*(m_fDirectionX/9.0f)),(int)m_fPosY+20+ (i * (m_fDirectionY/9.0f))) == TRUE)
					{
						BreakCar();
					}
				}
			}
			Accelerate();
		}/*COMPUTER CONTROL*/
	}

	

	//如果赛车被一个远端用户控制
	if(m_iControlType == CTRL_NETWORK_LOCAL &&
		GetRaceXApp()->m_bIsMultiplayer == TRUE &&
		!GetRaceXApp()->GetMultiplayer()->IsHosting() )
	{
		m_bRemoteKeyboardStatus = 0;

		//从远端读取键盘状态值
		if(pKeyboard.CheckKey(DIK_RIGHT))
		{
			m_bRemoteKeyboardStatus |= 0x01;
		}

		if(pKeyboard.CheckKey(DIK_LEFT))
		{
			m_bRemoteKeyboardStatus |= 0x02;
		}

		if(pKeyboard.CheckKey(DIK_DOWN))
		{
			m_bRemoteKeyboardStatus |= 0x04;
		}
		
		if(pKeyboard.CheckKey(DIK_UP))
		{
			m_bRemoteKeyboardStatus |= 0x08;
		}
		
		if(GetRaceXApp()->m_bSendKeyboard == TRUE || GetTickCount()-lLastMessage > 100)
		{
			GetRaceXApp()->GetMultiplayer()->SendTo(GetRaceXApp()->GetMultiplayer()->GetHost(), MSG_KEYBOARD_STATUS, &m_bRemoteKeyboardStatus, 1, 0/*DPNSEND_SYNC*/);
			GetRaceXApp()->m_bSendKeyboard = FALSE;
			lLastMessage = GetTickCount();
		}
	}
	
	if((GetRaceXApp()->m_bIsMultiplayer==TRUE&&GetRaceXApp()->GetMultiplayer()->IsHosting())||
		GetRaceXApp()->m_bIsMultiplayer == FALSE)
	{
		//处理完用户/电脑/网络输入后,重新定位赛车位置
		m_fPosY = m_fPosY + ((float)m_fDirectionY / 9.0f) * ((float)m_iSpeed / _SPEED_FACTOR_);
		m_fPosX = m_fPosX + ((float)m_fDirectionX / 9.0f) * ((float)m_iSpeed / _SPEED_FACTOR_);

		// Track control goes here
		// Check if we are passing throught a checkpoint or how far we are from thw
		// next check point
		if(m_iCarState == CARSTATE_OK)
		{
			if(m_iCheckPoint == -1)
			{
				if(theTrack->GetCheckPoint((int)m_fPosX+10,(int) m_fPosY+18) == 1)
				{
					m_iCheckPoint = 1;
					m_lCurrentTime = GetTickCount();

					iX = 0;
					iY = 0;
					m_iDistanceToNextCheckPoint = 999999999;
					do
					{
						iX = iX / 40;
						iY = iY / 40;
						theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
						if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
						{
							m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
						}
						if(iX != -1)
							iX += 40;
					}while(iX>0);
				}
			}
			else
			{
				if(theTrack->GetCheckPoint((int)m_fPosX+10, (int)m_fPosY+18) <= m_iCheckPoint)
				{
					if(theTrack->GetCheckPoint((int)m_fPosX+10, (int)m_fPosY+18) == 1 &&
					   m_iCheckPoint == theTrack->GetMaxCheckPoint())
					{
						m_vcLapTimes.push_back(GetTickCount()-m_lCurrentTime);
						m_lCurrentTime = GetTickCount();

						m_iCheckPoint = 1;

						iX = 0;
						iY = 0;
						m_iDistanceToNextCheckPoint = 999999999;
						do
						{
							iX = iX / 40;
							iY = iY / 40;
							theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
							if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
							{
								m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
							}

							if(iX != -1)
								iX += 40;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -