DrawPolygon3DBaseを使って、テクスチャーを
読み込んだのですが、うまくテクスチャーが表示
されません。
テクスチャーのサイズは、64×64です。
ソースコードを載せます。
#include"DxLib.h"
#include<windows.h>
#include<math.h>
#define RAD (3.14159265/180)
#define pi (3.14159265)
#define PI 3.1415926535
#define SITA(c) ((double)(c)*PI/180.0)
const float BaseCartPosX = 0.f, BaseCartPosY = 0.f, BaseCartPosZ = 0.f, BaseCartLengh = 4.f;
float DegToRad(float deg) { return deg * 1.74532925138889E-02f; }
VERTEX_3D CartVertex[] =
{
{ BaseCartPosX - BaseCartLengh, BaseCartPosY+BaseCartLengh, BaseCartPosZ, 255, 255, 255, 128, 0.f, 0.f },
{ BaseCartPosX - BaseCartLengh, BaseCartPosY-BaseCartLengh, BaseCartPosZ, 255, 255, 255, 128, 0.f, 1.f },
{ BaseCartPosX + BaseCartLengh, BaseCartPosY+BaseCartLengh, BaseCartPosZ, 255, 255, 255, 128, 1.f, 0.f },
{ BaseCartPosX + BaseCartLengh, BaseCartPosY-BaseCartLengh, BaseCartPosZ, 255, 255, 255, 128, 1.f, 1.f },
};
VECTOR NegativeVector(const VECTOR &v)
{
VECTOR rv;
rv.x = -v.x;
rv.y = -v.y;
rv.z = -v.z;
return rv;
}
VECTOR MakeVector(float x, float y, float z)
{
VECTOR v = { x, y, z };
return v;
}
VECTOR AddVector(const VECTOR &v1, const VECTOR &v2)
{
VECTOR v;
v.x = v1.x + v2.x;
v.y = v1.y + v2.y;
v.z = v1.z + v2.z;
return v;
}
VECTOR SubVector(const VECTOR &v1, const VECTOR &v2)
{
VECTOR v;
v.x = v1.x - v2.x;
v.y = v1.y - v2.y;
v.z = v1.z - v2.z;
return v;
}
VECTOR MultiVectorScaler(const VECTOR &v1, float k)
{
VECTOR v;
v.x = v1.x * k;
v.y = v1.y * k;
v.z = v1.z * k;
return v;
}
// 内積
float DotProduct(const VECTOR &v1, const VECTOR &v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
// 長さ
float VectorLength(const VECTOR &v)
{
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
// 単位化
VECTOR NormalizeVector(const VECTOR v)
{
VECTOR r;
float len = VectorLength(v);
if(len > 0.f)
{
float invLen = 1.f / len;
r.x = v.x * invLen;
r.y = v.y * invLen;
r.z = v.z * invLen;
}
else
{
r.x = r.y = r.z = 0.f;
}
return r;
}
// なす角度
float GetVectorAngle(const VECTOR &v1, const VECTOR &v2)
{
float r = DotProduct(v1, v2);
if(r > 1.f) r = 1.f;
else
if(r < -1.f) r = -1.f;
return acos(r);
}
// ベクトル補完
VECTOR VectorSlerp(const VECTOR &src, const VECTOR &dest, float t)
{
float theta = DotProduct(src, dest);
float invT = 1.0f - t;
VECTOR src_v;
VECTOR dest_v;
if(theta < 0.0f)
{
src_v = NegativeVector(src_v);
theta = -theta;
}
else
src_v = src;
float scale1;
float scale2;
if(theta + 1.0f > 0.05f)
{
if(1.0f - theta < 0.05f)
{
scale1 = invT;
scale2 = t;
}
else
{
float cos_v = cosf(theta);
float sin_v = 1.0f / sinf(cos_v);
scale1 = sinf(cos_v * invT);
scale2 = sinf(cos_v * t);
scale1 *= sin_v;
scale2 *= sin_v;
}
dest_v = dest;
}
else
{
dest_v.x = -src_v.y;
dest_v.y = src_v.x;
dest_v.z = -src_v.z;
scale1 = sinf(pi * (0.5f - t));
scale2 = sinf(pi * t);
}
return MakeVector
(
scale1 * src_v.x + scale2 * dest_v.x,
scale1 * src_v.y + scale2 * dest_v.y,
scale1 * src_v.z + scale2 * dest_v.z
);
}
void Trans(int *x,int *y,int xx,int zz)
{
if(xx>160.0 && zz<250)//右下
{
*x=1000+xx-160;
*y=1000+zz*-1;
}
else if(xx>160.0 && zz>=250)//右上
{
*x=1000+xx-160;
*y=1000-zz;
}
else if(xx<=160.0 && zz<250)//左上
{
*x=1000-(-xx)-160;
*y=1000-zz;
}
else if(xx<=160.0 && zz>=250) //左下
{
*x=1000-(-xx)-160;
*y=1000+zz*-1;
}
}
class Camera{
public:
Camera()
{
m_Pos.x= 204.3; m_Pos.y=0.f; m_Pos.z = 614.9f;
m_Target.x = m_Target.y = 0.f;
m_Target.z = 1.f;
m_Up.x = m_Up.z = 0.f;
m_Up.y = 1.f;
Update();
}
void Update()
{
CreateLookAtMatrix(&m_Matrix, &m_Pos, &m_Target, &m_Up);
SetTransformToView(&m_Matrix);
}
const VECTOR &GetPosition() { return m_Pos; }
void SetPosition(const VECTOR &p) { m_Pos = p; }
const VECTOR &GetTarget() { return m_Target; }
void SetTarget(const VECTOR &t) { m_Target = t; }
const VECTOR GetAtVector() { return SubVector(m_Target, m_Pos); }
void SetAtVector(const VECTOR &at) { m_Target = AddVector(at, m_Pos); }
const VECTOR &GetUpVector() { return m_Up; }
void SetUpVector(const VECTOR &up) { m_Up = up; }
VECTOR m_Pos;
VECTOR m_Target;
VECTOR m_Up;
MATRIX m_Matrix;
};
Camera camera;
class Cart{
public:
Cart()
{
m_Pos.x =204.3f; m_Pos.z = 614.9f, m_Pos.y = 1.f;
m_Vec.x = m_Vec.y = 0.f, m_Vec.z = 1.f;
m_Thruster.x = m_Thruster.y = m_Thruster.z = 0.f;
m_Acc.x = m_Acc.y = m_Acc.z = 0.f;
m_RotY =-2.442 ;m_AddRotY = m_AccRotY = 0.f;
m_Speed = 0;
m_Img = -1;
m_Reduce = 0.99f;
}
void LoadImage() { m_Img = LoadGraph("./DATA/cart.png"); }
void Accelerator(float power) { m_Acc = AddVector(m_Acc, MultiVectorScaler(m_Vec, power)); }
void Turn(float rad) { m_AccRotY += rad; }
void Turn_AdjustSpeed(float rad) { m_AccRotY += rad * m_Speed * 0.5f; }
void SetReduce(float reduce) { m_Reduce = reduce; }
float GetReduce() const { return m_Reduce; }
void Update()
{
m_Thruster = AddVector(m_Thruster, m_Acc);
m_Pos = AddVector(m_Pos, m_Thruster);
m_Speed = VectorLength(m_Thruster);
m_Thruster = MultiVectorScaler(m_Thruster, 0.96f);
m_Acc = MakeVector(0, 0, 0);
m_AddRotY += m_AccRotY;
m_RotY += m_AddRotY;
VECTOR mv=MakeVector(0,0,1);
VectorRotationY(&m_Vec, &mv, -m_RotY);
m_AddRotY *= 0.92f;
m_AccRotY = 0.f;
}
void Draw(int flag)
{
int ry;
MATRIX m, matTrans, matRotY;
ry=((int)(m_RotY*RAD)-180+360)%360;
CreateTranslationMatrix(&matTrans, m_Pos.x, m_Pos.y, m_Pos.z);
//CreateIdentityMatrix( &matRotY ) ;
CreateRotationYMatrix(&matRotY,m_RotY);
CreateMultiplyMatrix(&m, &matRotY, &matTrans);
//CreateMultiplyMatrix(&m,&camera.m_Matrix,&matTrans);
SetTransformToWorld(&m);
if(flag==0)
{
DrawGraph(160.0-(96/2),120-(96/2), m_Img, TRUE ) ;
}
else if(flag==1)
{
DrawGraph3D( m_Pos.x, m_Pos.y, m_Pos.z, m_Img, TRUE ) ;
}
else if(flag==2)
{
VECTOR a=MakeVector(m_Pos.x,m_Pos.y,m_Pos.z);
VECTOR b=MakeVector(m_Pos.x+5.0f,m_Pos.y+5.0f,m_Pos.z+5.0f);
DrawPolygon3DBase(CartVertex, 4, DX_PRIMTYPE_TRIANGLESTRIP, m_Img, FALSE);
//DrawCube3D( a, b, GetColor(255,0,0), TRUE ) ;
}
}
void DebugDraw()
{
int line = 20, lineStep = 12;
DrawFormatString(0, line, GetColor(255, 0, 0), "pos %.1f %.1f %.1f", m_Pos.x, m_Pos.y, m_Pos.z);
DrawFormatString(0, line += lineStep, GetColor(255, 0, 0), "rotY %.3f", m_RotY);
DrawFormatString(0, line += lineStep, GetColor(255, 0, 0), "speed %.3f", m_Speed);
}
const VECTOR &GetPosition() const { return m_Pos; }
const VECTOR &GetVector() const { return m_Vec; }
float GetSpeed() const { return m_Speed; }
float GetRotateY() const { return m_RotY; }
float GetAddRotateY() const { return m_AddRotY; }
void UpdateParameter()
{
// 進行方向と加速の向きが違うときの抵抗
float rate = 1.f;
if(VectorLength(m_Vec) > 0.01f)
{
float angle = GetVectorAngle(NormalizeVector(m_Thruster), m_Vec);
rate = fabs(angle) / (pi * 2.f);
rate *= rate;
rate = 1.f - powf(rate, 1.2f);
}
m_Thruster = MultiVectorScaler(m_Thruster, m_Reduce * rate);
m_Thruster = AddVector(m_Thruster, m_Acc);
// 位置更新
m_Pos = AddVector(m_Pos, m_Thruster);
m_AddRotY += m_AccRotY;
m_RotY += m_AddRotY;
VECTOR mv=MakeVector(0,0,1);
VectorRotationY(&m_Vec, &mv, -m_RotY);
m_Speed = VectorLength(m_Thruster);
}
void UpdateMatrix()
{
MATRIX matTrans, matRotY, matRotZ;
CreateTranslationMatrix(&matTrans, m_Pos.x, m_Pos.y, m_Pos.z);
CreateRotationYMatrix(&matRotY, m_RotY);
CreateRotationZMatrix(&matRotZ, m_AddRotY * 7.f);
CreateMultiplyMatrix(&m_Matrix, &matRotY, &matTrans);
CreateMultiplyMatrix(&m_Matrix, &matRotZ, &m_Matrix);
}
MATRIX m_Matrix;
VECTOR m_Pos;
VECTOR m_Vec;
VECTOR m_Thruster;
VECTOR m_Acc;
float m_RotY;
float m_AddRotY;
float m_AccRotY;
float m_Speed;
float m_Reduce;
int m_Img;
};
VECTOR Camera_;
VECTOR cart;
VECTOR up;
float CameraRot;
MATRIX CameraMatrix;
int GrHandle ;
int GrHandle2 ;
VERTEX_3D Vertex[6] ; // ポリゴン2枚なので、頂点は6個
Cart cart_;
Cart EnemyCart;
long FrameNumber=0;
VECTOR SetXYZ[60*60*10]={0};
float SetAngleY[60*60*10]={0};
unsigned char keydata[60*60*10]={0};
int font;
void GetPixel3(int x,int y,int *r,int *g,int *b,int *a)
{
GetPixelSoftImage(GrHandle2,x,y,r,g,b,a ) ;
}
void ChaseCamera()
{
const VECTOR &cartPos = cart_.GetPosition();
const VECTOR &cartVec = cart_.GetVector();
const VECTOR &cameraPos = camera.GetPosition();
{
float height = 15.f - cart_.GetSpeed() * 4.f;
float height2 = 8.f;
const float length = 25.f;
camera.SetPosition(AddVector(cartPos, MakeVector(cartVec.x * -length, height2, cartVec.z * -length)));
camera.SetAtVector(VectorSlerp(camera.GetAtVector(), SubVector(cartPos, cameraPos), 0.2f));
}
{
MATRIX m, tmat;
CreateRotationYMatrix(&m, cart_.GetRotateY());
///CreateRotationZMatrix(&tmat, cart_.GetAddRotateY() * 8.f);
CreateIdentityMatrix( &tmat ) ;
CreateMultiplyMatrix(&m, &tmat, &m);
VECTOR up = { 0, 1, 0 };
VectorTransform(&up, &up, &m);
camera.SetUpVector(up);
}
camera.Update();
}
void Init()
{
font=CreateFontToHandle( NULL , 50 , 5 ,
DX_FONTTYPE_ANTIALIASING_EDGE) ;
Camera_.y=130.0F;
Camera_.x=160.0F;
Camera_.z=750.0F;
cart.x=160.0F;
cart.y=120.0F;
cart.z=800.0F;
up.x=0.0F;
up.y=1.0F;
up.z=0.0F;
camera.SetPosition(MakeVector(1, 10, 50));
camera.SetTarget(MakeVector(0, 0, 0));
CameraRot = 0; // カメラの向き (ビットマップのx方向を 0 度として時計回りに 360 度回転で指定)
CreateIdentityMatrix( &CameraMatrix ) ;// カメラ行列
GrHandle = LoadGraph( "./DATA/cource01.png" ) ;
GrHandle2 = LoadSoftImage( "./DATA/courcedat.png" ) ;
SetUseDivGraphFlag(FALSE) ;
cart_.LoadImage();
EnemyCart.LoadImage();
// 頂点情報のセット
{
// 画面の中央に幅・高さ100で描画
Vertex[0].pos.x = 160.0F - 1000.0F ; Vertex[0].pos.y = 0.0F ; Vertex[0].pos.z = 1000.0F ;
Vertex[0].u = 0.0F ;
Vertex[0].v = 0.0F ;
Vertex[1].pos.x = 160.0F + 1000.0F ; Vertex[1].pos.y = 0.0F + 0.0F ; Vertex[1].pos.z = 1000.0F ;
Vertex[1].u = 1.0F ;
Vertex[1].v = 0.0F ;
Vertex[2].pos.x = 160.0F - 1000.0F ; Vertex[2].pos.y = 0.0F - 0.0F ; Vertex[2].pos.z = -500.0F ;
Vertex[2].u = 0.0F ;
Vertex[2].v = 1.0F ;
Vertex[3].pos.x = 160.0F + 1000.0F ; Vertex[3].pos.y = 0.0F - 0.0F ; Vertex[3].pos.z = -500.0F ;
Vertex[3].u = 1.0F ;
Vertex[3].v = 1.0F ;
Vertex[4].pos.x = 160.0F - 1000.0F ; Vertex[4].pos.y = 0.0F - 0.0F ; Vertex[4].pos.z = -500.0F ;
Vertex[4].u = 0.0F ;
Vertex[4].v = 1.0F ;
Vertex[5].pos.x = 160.0F + 1000.0F ; Vertex[5].pos.y = 0.0F + 0.0F ; Vertex[5].pos.z = 1000.0F ;
Vertex[5].u = 1.0F ;
Vertex[5].v = 0.0F ;
// 輝度は全要素100%
Vertex[0].r = Vertex[0].g = Vertex[0].b = 255 ;
Vertex[1].r = Vertex[1].g = Vertex[1].b = 255 ;
Vertex[2].r = Vertex[2].g = Vertex[2].b = 255 ;
Vertex[3].r = Vertex[3].g = Vertex[3].b = 255 ;
Vertex[4].r = Vertex[4].g = Vertex[4].b = 255 ;
Vertex[5].r = Vertex[5].g = Vertex[5].b = 255 ;
// a も最大値
Vertex[0].a = 255 ;
Vertex[1].a = 255 ;
Vertex[2].a = 255 ;
Vertex[3].a = 255 ;
Vertex[4].a = 255 ;
Vertex[5].a = 255 ;
}
}
void BillBoard()
{
}
int GetX,GetY;
int FPScount=0;
int r,g,b,a;
void ShowFPS(void)
{
static long time=GetTickCount();
static int FPS=0;
if(GetTickCount()-time>1000)
{
FPS=FPScount;
time=GetTickCount();
FPScount=0;
}
DrawFormatString( 0 , 0 , GetColor(255,0,0) ,
"FPS=%d" , FPS ) ;
DrawFormatString( 0 , 240-20 , GetColor(255,0,0) ,
"m_Img=%d" , EnemyCart.m_Img) ;
/*
DrawFormatString( 0 , 240-20 , GetColor(255,0,0) ,
"GX=%d:GY=%d" , GetX,GetY ) ;
DrawFormatString( 0 , 240-40 , GetColor(255,0,0) ,
"(%d,%d,%d)" , r,g,b ) ;
*/
}
void Check()
{
//当たり判定(かなり強引)
if(cart_.m_Pos.x>160.0+1000.0f) cart_.m_Pos.x=160.0+1000.0f;
if(cart_.m_Pos.x<160.0-1000.0f) cart_.m_Pos.x=160.0-1000.0f;
if(cart_.m_Pos.z>1000.0f)cart_.m_Pos.z=1000.0f;
if(cart_.m_Pos.z<-500.0f)cart_.m_Pos.z=-500.0f;
if(cart_.m_Pos.x>160.0 && cart_.m_Pos.z<250)//右下
{
GetX=1000+cart_.m_Pos.x-160;
GetY=1000+cart_.m_Pos.z*-1;
}
else if(cart_.m_Pos.x>160.0 && cart_.m_Pos.z>=250)//右上
{
GetX=1000+cart_.m_Pos.x-160;
GetY=1000-cart_.m_Pos.z;
}
else if(cart_.m_Pos.x<=160.0 && cart_.m_Pos.z<250)//左上
{
GetX=1000-(-cart_.m_Pos.x)-160;
GetY=1000-cart_.m_Pos.z;
}
else if(cart_.m_Pos.x<=160.0 && cart_.m_Pos.z>=250) //左下
{
GetX=1000-(-cart_.m_Pos.x)-160;
GetY=1000+cart_.m_Pos.z*-1;
}
GetPixel3(GetX,GetY,&r,&g,&b,&a);
if(g==255)
cart_.SetReduce(cart_.GetReduce() * 0.998f);
//cart_.SetReduce(cart_.GetReduce() * 0.2f);
else
cart_.SetReduce(0.99f);
//コースが緑色だったら、スピードを落とす
}
void GetRePlay()
{
//SetXYZ[FrameNumber]=cart_.m_Pos;
//SetAngleY[FrameNumber]=cart_.m_RotY;
/*if(leftが押されている) keydat |= (1 << 0);
if(upが押されている) keydat |= (1 << 1);
if(rightが押されている) keydat |= (1 << 2);
if(downが押されている) keydat |= (1 << 3);
*/
keydata[FrameNumber]=0;
if(CheckHitKey(KEY_INPUT_LEFT))
keydata[FrameNumber] |= (1 << 0);
if(CheckHitKey(KEY_INPUT_X))
keydata[FrameNumber] |= (1 << 1);
if(CheckHitKey(KEY_INPUT_RIGHT))
keydata[FrameNumber] |= (1 << 2);
if(CheckHitKey(KEY_INPUT_C) || CheckHitKey(KEY_INPUT_Z))
keydata[FrameNumber] |= (1 << 3);
}
void SetRePlay()
{
static int flag=0;
if(flag==0)
{
FILE *fp;
fp=fopen("./DATA/enm.dat","rb");
//fread(SetXYZ,sizeof(SetXYZ),1,fp);
//fread(SetAngleY,sizeof(SetAngleY),1,fp);
fread(keydata,sizeof(keydata),1,fp);
fclose(fp);
flag=1;
}
if(keydata[FrameNumber] & (1 << 0)) // leftが押されている
EnemyCart.Turn_AdjustSpeed(-DegToRad(0.1f));
if(keydata[FrameNumber] & (1 << 1)) // upが押されている
EnemyCart.Accelerator(0.1f);
if(keydata[FrameNumber] & (1 << 2)) // rightが押されている
EnemyCart.Turn_AdjustSpeed(DegToRad(0.1f));
if(keydata[FrameNumber] & (1 << 3)) // downが押されている
EnemyCart.Accelerator(-0.03f);
EnemyCart.Update();
//cart_.Update();
//EnemyCart.m_Pos =SetXYZ[FrameNumber];
//EnemyCart.m_RotY=SetAngleY[FrameNumber];
}
void MoveCart()
{
if(CheckHitKey(KEY_INPUT_X))
{
cart_.Accelerator(0.1f);
}
if(CheckHitKey(KEY_INPUT_Z) || CheckHitKey(KEY_INPUT_C))
{
cart_.Accelerator(-0.03f);
}
if(CheckHitKey(KEY_INPUT_LEFT))
{
cart_.Turn_AdjustSpeed(-DegToRad(0.1f));
}
if(CheckHitKey(KEY_INPUT_RIGHT)){
cart_.Turn_AdjustSpeed(DegToRad(0.1f));
}
cart_.Update();
}
int CountUp(void)
{
static int cnt=0;
static int number=3;
DrawFormatStringToHandle( 160-25, 120-25 , GetColor(255,255,255) ,
font , "%d" , number ) ;
cnt++;
if(cnt>60)
{
number--;
cnt=0;
if(number<0){number=3;cnt=0;return 1;}
}
return 0;
}
void MainLoop()
{
static int flag2=0;
MATRIX m;
CreateIdentityMatrix(&m);
SetTransformToWorld(&m);
FPScount++;
BillBoard();
if(flag2==1){
SetRePlay();//リプレイデータを再現する
MoveCart();//カートの移動
ChaseCamera();//カメラの追跡
Check();//当たり判定
//GetRePlay();//リプレイデータを生成する
// ポリゴンを透過色無しで2枚描画
}
DrawPolygon3D( Vertex, 2, GrHandle, FALSE ) ;
cart_.Draw(0);
EnemyCart.Draw(2);
ShowFPS();
//cart_.DebugDraw();
if(flag2==1)
{
static int flag=0;
static int cnt=0;
if(r==255 && g==255 && b==255 && flag==0)
{
flag=1;
cnt++;
}else if(r!=255 && g!=255 && b!=255){
flag=0;
}
if(cnt<3)
{
FrameNumber++;
DrawFormatString( 0 , 240-60 , GetColor(255,0,0) ,
"%d周目です。" , cnt) ;
}
else
{
DrawFormatString( 0 , 240-60 , GetColor(255,0,0) ,
"走行完了") ;
static int flag=0;
if(flag==0)
{
FILE *fp;
fp=fopen("./DATA/enm.dat","wb");
//fwrite(SetXYZ,sizeof(SetXYZ),1,fp);
//fwrite(SetAngleY,sizeof(SetAngleY),1,fp);
fwrite(keydata,sizeof(keydata),1,fp);
fclose(fp);
flag=1;
}
}
}
if(flag2==0)
{
if(CountUp()==1)
{
flag2=1;
}
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hP,LPSTR lpC,int nC)
{
SetGraphMode(320,240,16);
SetMainWindowText("レースゲーム"); //ウィンドウのタイトル
ChangeWindowMode( TRUE ) ;
if(DxLib_Init() == -1) return (-1); //DXライブラリ初期化
SetDrawScreen(DX_SCREEN_BACK);
Init();
PlayMusic("./DATA/racing.mp3" ,DX_PLAYTYPE_LOOP) ;
//メインループ
while(ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){
ProcessMessage();
ClsDrawScreen(); //画面を初期化
MainLoop();
ScreenFlip(); //フリップする
}
// 使い終わったら解放
DxLib_End(); //DXライブラリ終了処理
return (0); //終了
}