rigid body
점프킹
겉보기상
ㄴ공주 만나서 fade out 하는 엔딩
ㄴUI - 굳이 - Game시작은 있어도 좋을 듯
(그냥 단순히 Press Sapce to Start)
ㄴ점프 위치 미리표시? - 점프 잔상 남기기?
ㄴ점프 게이지? - 35단계임을 알리기
ㄴ점프 수치조정 UI만들기?
코드상
ㄴeffective cpp
ㄴexcel 에 적어놓은것들
ㄴnamespace 등
rigid 안될 경우 비상책
#include "stdafx.h"
#include "Player.h"
HRESULT Player::init(void)
{
// 애니메이션 추가. 상태에 따라 전환할 이미지들.
_pWalk = IMAGEMANAGER->addFrameImage("걷기", "Resources/Images/Walk.bmp", 124*ZOOM, 54*ZOOM, 4, 2, true, RGB(255, 0, 255)); // 31 x 27
_pJump = IMAGEMANAGER->addFrameImage("점프", "Resources/Images/Jump.bmp", 90*ZOOM, 64*ZOOM, 3, 2, true, RGB(255, 0, 255)); // 30 x 32
_pStatus = IMAGEMANAGER->addFrameImage("상태", "Resources/Images/Status.bmp", 87*ZOOM, 56*ZOOM, 3, 2, true, RGB(255, 0, 255)); // 29 x 28 // 최대 : 31 x 32
// px, py는 플레이어 사각형의 실제 위치를 의미, 시작위치
_px = WINSIZE_X / 2;
_py = WINSIZE_Y / 2;
// px, py를 중앙으로 하는 캐릭터 최대크기의 사각형을 생성.
_rcPlayer = RectMakeCenter(_px, _py, P_WIDTH, P_HEIGHT);
// _probeY - 실제로 충돌을 판단할 개체
// _probeY는 최종적으로 _pWalk의 바닥이 된다. 맨 바닥으로 둔다.
//_probeY = _py + P_HEIGHT;
//
//_probeLX = _px - P_WIDTH / 2;
//_probeRX = _px + P_WIDTH / 2;
isGround = false;
isHit = false;
isCharge = false;
isLeft = false;
isIdle = true;
tIsInAirStart = chrono::system_clock::now();
return S_OK;
}
void Player::release(void)
{
SAFE_DELETE(_pWalk);
}
void Player::update(void)
{
// 중앙이 이동한다.
/// 좌 우 이동.
if (KEYMANAGER->isStayKeyDown(VK_RIGHT))
{
if (!isJump)
{
isLeft = false;
isIdle = false;
}
if (isGround && !isCharge )
{
_px += 4.0f;
_walkCnt++;
if (_walkCnt % 7 == 0)
{
_walkIdx++;
if (_walkIdx > 4)
{
_walkIdx = 0; // 최소로 다시
}
}
IMAGEMANAGER->findImage("걷기")->setFrameX(_walkIdx);
}
}
if (KEYMANAGER->isStayKeyDown(VK_LEFT))
{
if (!isJump)
{
isLeft = true;
isIdle = false;
}
if (isGround && !isCharge )
{
_px -= 4.0f;
_walkCnt++;
if (_walkCnt % 7 == 0)
{
_walkIdx--;
if (_walkIdx < 0)
{
_walkIdx = 4; // 최대로 다시
}
}
IMAGEMANAGER->findImage("걷기")->setFrameX(_walkIdx);
}
}
// 방향
_pWalk->setFrameY(isLeft);
_pJump->setFrameY(isLeft);
_pStatus->setFrameY(isLeft);
if(KEYMANAGER->isOnceKeyUp(VK_RIGHT) || KEYMANAGER->isOnceKeyUp(VK_LEFT))
{
isIdle = true;
IMAGEMANAGER->findImage("상태")->setFrameX(0);
IMAGEMANAGER->findImage("상태")->setFrameY(isLeft);
}
if (KEYMANAGER->isStayKeyDown(VK_SPACE) && isGround)
{
if (!isCharge)
{
tChargeStart = chrono::system_clock::now();
}
isCharge = true;
IMAGEMANAGER->findImage("점프")->setFrameX(0);
IMAGEMANAGER->findImage("점프")->setFrameY(isLeft);
}
// 안의 내용물을 함수로 만들어 일정 초 이상이면 강제점프 구현할 수 있을 듯
if (KEYMANAGER->isOnceKeyUp(VK_SPACE) && isCharge)
{
// 여기서 점프 함수가 들어와야 할 듯
isCharge = false;
_pJumpPower = (std::chrono::duration_cast<std::chrono::milliseconds>(chrono::system_clock::now() - tChargeStart)).count();
///_py -= 500.0f; 이게 실질적으로 점프시켜줬던 것..
IMAGEMANAGER->findImage("점프")->setFrameX(1);
IMAGEMANAGER->findImage("점프")->setFrameY(isLeft);
cout << "aaaaaaaaaaaaaaaaa";
isJump = true;
}
/// 아래 2개는 없어져야 함.
if (KEYMANAGER->isStayKeyDown(VK_UP))
{
_py -= 130.0f;
}
if (KEYMANAGER->isStayKeyDown(VK_DOWN))
{
_py += 30.0f;
}
_probeLX = _px - P_WIDTH / 2;
_probeRX = _px + P_WIDTH / 2;
_probeFOOT = _py + P_HEIGHT/2; // 그냥 갱신되는 값을 의미하는 건가?? - probeY의 위치는 항상 밑바닥이어야 함
_probeHEAD = _py - P_HEIGHT / 2;
_rcPlayer = RectMakeCenter(_px, _py, P_WIDTH, P_HEIGHT);
/// _probeFOOT - 30 으로 해야만 땅에 안 박힘?? - 항상 안쪽부터 하자 . 그렇지 않으면 자석 - 함수화하는게?
//for (int i = _probeFOOT; i > _probeFOOT- P_HEIGHT/2-10; i--)
for (int i= _probeFOOT - P_HEIGHT / 2 - 10; i < _probeFOOT + 10; i++)
{
// px라는 rc의 중앙값, 그리고 현재 비교중인 i값을 가져와 pixel을 검출한다.
COLORREF pixelColor = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px, i);
COLORREF pixelColor2 = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px - 25, i);
COLORREF pixelColor3 = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px + 25, i);
//if (pixelColor == RGB(255,0,255))
if (pixelColor == RGB(255,0,255) && pixelColor2 == RGB(255, 0, 255) && pixelColor3 == RGB(255, 0, 255))
{
///_pInAirSec
if (isGround)
{
tIsInAirStart = chrono::system_clock::now();
}
isGround = false;
}
else if (pixelColor == RGB(0, 0, 0) || pixelColor2 == RGB(0, 0, 0) || pixelColor3 == RGB(0, 0, 0)) // || pixelColor2 == RGB(0, 0, 0))
{
//if (isJump) isJump = false;
isGround = true;
/// 이거 일단 종료
//isJump = false; _pJumpPower = 0;
i <= _probeFOOT ? _py -= (_probeFOOT - i) : _py += (i-_probeFOOT);
//cout << "i :" << i << " _probeFoot : " << _probeFOOT << "\n";
break; //break가 없어서 그랬다... ㅎㅎ
}
else if(pixelColor == RGB(255,0,0) || pixelColor2 == RGB(255, 0, 0) || pixelColor3 == RGB(255, 0, 0)) // || pixelColor2 == RGB(255, 0, 0)) // 빨강 or 회색 = 미끄러짐 - 추후 수정?
{
IMAGEMANAGER->findImage("점프")->setFrameX(2);
_px -= 10;
}
}
//Rectangle(getMemDC(), _px - 25 - 4, _probeHEAD + P_HEIGHT / 2 - 10, _px -25+ 4, _probeHEAD);
/// _probeHEAD
for (int i = _probeHEAD + P_HEIGHT / 2 - 10; i > _probeHEAD ; i--) /// 굳이 붙을 필요가 없다. 따라서 그냥 _probeHEAD 까지 - foot은 어쩔 수 없는 경우가 있었고, 바닥에 붙어야만 했다.
{
// px라는 rc의 중앙값, 그리고 현재 비교중인 i값을 가져와 pixel을 검출한다.
COLORREF pixelColor = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px, i);
COLORREF pixelColor2 = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px-25, i);
COLORREF pixelColor3 = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), _px+25, i);
/// 중력
if (pixelColor == RGB(0, 0, 0) || pixelColor2 == RGB(0, 0, 0) || pixelColor3 == RGB(0, 0, 0))
{
//_py += GRAVITY;
i >= _probeHEAD ? _py += (i - _probeHEAD) : _py -= (_probeHEAD - i);
//isJump = false;
break;
}
}
/// _probeLX, _probeRX
for (int i = _probeLX + 10; i > _probeLX; i--) /// 굳이 붙을 필요가 없다.
{
COLORREF pixelColor = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), i, _py+20);
/// 중력
if (pixelColor == RGB(0, 0, 0))
{
//_py += GRAVITY;
i >= _probeLX ? _px += (i - _probeLX) : _py -= (_probeLX - i);
cout << "PROBE LX LX";
break;
}
}
for (int i = _probeRX - 10; i < _probeRX; i++) /// 굳이 붙을 필요가 없다.
{
COLORREF pixelColor = GetPixel(IMAGEMANAGER->findImage("MapMaskPart")->getMemDC(), i, _py + 20);
/// 중력
if (pixelColor == RGB(0, 0, 0))
{
//_py += GRAVITY;
i <= _probeRX ? _px -= (_probeRX - i) : _px += (i - _probeRX);
cout << "PROBE RX RX";
break;
}
}
//cout << "isGround?? : " << isGround << "\n";
_pInAirSec = (std::chrono::duration_cast<std::chrono::milliseconds>(chrono::system_clock::now() - tIsInAirStart)).count();
if (!isGround && !isJump)
{
/* - 이런식으로 잘게 쪼개서 10프레임마다 진행되도록 어떻게?
static int jum = 0;
static bool isPeak = false;
_pInAirSec = (std::chrono::duration_cast<std::chrono::milliseconds>(chrono::system_clock::now() - tIsInAirStart)).count();
//_py += GRAVITY * (_pInAirSec/300) -_pJumpPower/100;
if (jum <= _pJumpPower && !isPeak)
{
jum++;
}
else
{
jum--;
if (jum <= 0)
{
jum = 0;
}
}
*/
// 점프는 하는데.. y값이 서서히 변하게부터 어떻게 해보자..
_py += GRAVITY * (_pInAirSec / 200);
// isJump는 점프가 다 완료한 후에만 false로 변환
// JumpPower도 0으로 전환 - 일단 둘 다 그냥 땅에 닿는경우 초기화..
}
// 여기부분 수정
if (isJump)
{
/* 원본
_py += GRAVITY * (_pInAirSec / 200);
int dx, dy;
_pJumpPower >= MAX_JUMP ? _pJumpPower = MAX_JUMP : _pJumpPower;
//(_pJumpPower / 10) >= MAX_JUMP ? dy = MAX_JUMP : dy = (_pJumpPower / 10);
dy = (_pJumpPower / 10);
_py -= dy; /// _pJumpPower = milliseconds 765 735
_py += GRAVITY;
_pJumpPower -= 10;
if (_pJumpPower <= 0)
{
isJump = false;
}
*/
_pJumpPower >= MAX_JUMP ? _pJumpPower = MAX_JUMP : _pJumpPower;
//(_pJumpPower / 10) >= MAX_JUMP ? dy = MAX_JUMP : dy = (_pJumpPower / 10);
int jj = _pJumpPower;
dy = jj / 20;
_py -= dy; /// _pJumpPower = milliseconds 765 735
_py += GRAVITY * (_pInAirSec / 200)/ 2;
if (isLeft) dx = -5;
else dx = 5;
_px += dx;
_pJumpPower -= 5;
if (_pJumpPower <= 0)
{
isJump = false;
}
}
chrono::duration<double>s = chrono::system_clock::now() - SYS_TIME;
// 여기서 초기화해줘야만 함
//cout << _pJumpPower;
if (isJump) cout << _pJumpPower << " : " << _pJumpPower / 10 << "\n";
}
/*
bool isGround; // 공중인가 땅인가
bool isHit; // 위든 옆이든 맞았는가 // 위면 바로 떨어지기, 옆이면 반사해서 살짝위로 갔다가 반대로 떨어기지
bool isCharge;
bool isIdle; // 중앙
bool isLeft;
*/
// 3가지 애니메이션만 있어야 할 듯
void Player::render(void)
{
if (isGround && !isCharge && !isIdle)
{
_pWalk->frameRender(getMemDC(), _rcPlayer.left, _rcPlayer.top + 10);
}
else if ((isGround && isCharge) || !isGround) // isHit 제외, isIdle 제외 - isLeft와 같이 사용해서 점프방향 정할거임.
{
_pJump->frameRender(getMemDC(), _rcPlayer.left, _rcPlayer.top-3);
}
else if (isIdle) // || isHit - 엎드리기도 있다. - 최고높이 기록?
{
_pStatus->frameRender(getMemDC(), _rcPlayer.left, _rcPlayer.top+10);
}
if (KEYMANAGER->isToggleKeyDown(VK_F1))
{
Rectangle(getMemDC(), _rcPlayer.left, _rcPlayer.top, _rcPlayer.right, _rcPlayer.bottom);
// PROBE Foot
Rectangle(getMemDC(), _px-4, _probeFOOT + 0, _px + 4, _probeFOOT - P_HEIGHT / 2 + 10);
Rectangle(getMemDC(), _px - 25 -4, _probeFOOT + 0, _px - 25 + 4, _probeFOOT - P_HEIGHT / 2 + 10);
Rectangle(getMemDC(), _px + 25 -4, _probeFOOT + 0, _px + 25 + 4, _probeFOOT - P_HEIGHT / 2 + 10);
Rectangle(getMemDC(), _probeLX - 3, _py +20, _probeLX + 3, _py+26);
Rectangle(getMemDC(), _probeRX - 3, _py +20, _probeRX + 3, _py+26);
Rectangle(getMemDC(), _px - 4, _probeHEAD + P_HEIGHT / 2 - 10, _px + 4, _probeHEAD);
Rectangle(getMemDC(), _px - 25 - 4, _probeHEAD + P_HEIGHT / 2 - 10, _px -25+ 4, _probeHEAD);
Rectangle(getMemDC(), _px + 25 - 4, _probeHEAD + P_HEIGHT / 2 - 10, _px +25+ 4, _probeHEAD);
}
}
void Player::SetPlayerY(float y)
{
_py = y;
}
float Player::GetPlayerY()
{
return _py;
}
#pragma once
#include "GameNode.h"
#define SPD 4
#define P_WIDTH 31 * ZOOM
#define P_HEIGHT 32 * ZOOM
const float GRAVITY = 4.0f;
const float MAX_JUMP = 450.0f;
struct stCollision
{
RECT rc;
bool bBlockBottom = true;
// 여러 bool 값들.
bool sdaf = false;
};
class Player : public GameNode
{
// 이미지 넣어두기
// 소리 넣어두기
// 출력 적절히 하게 하기
// ImageManager 대신 사용.
private:
/// Image
GImage* _pWalk;
GImage* _pJump;
GImage* _pStatus;
/// RECT / x, y / probe
RECT _rcPlayer;
int _probeFOOT;
int _probeHEAD;
int _probeLX;
int _probeRX;
float _px, _py;
int dx = 0; // x 변화량 - 이동량을 바탕으로 애니메이션을 변환
int dy = 0;
/// Animation Var
int _walkCnt = 0;
int _walkIdx = 0;
/// Status
bool isGround; // 공중인가 땅인가
bool isHit; // 위든 옆이든 맞았는가 // 위면 바로 떨어지기, 옆이면 반사해서 살짝위로 갔다가 반대로 떨어기지
bool isCharge;
bool isLeft; // 0 = right / 1 = left / 2 = mid
bool isJump; // 그냥 !isGround의 떨어지는 것과 계산적으로만 구분하기 위함.
bool isIdle;
/// Time
chrono::system_clock::time_point tChargeStart;
chrono::system_clock::time_point tIsInAirStart;
long long _pJumpPower;
long long _pInAirSec;
public:
HRESULT init(void);
void release(void);
void update(void);
void render(void);
float GetPlayerY();
void SetPlayerY(float y);
Player() { };
~Player() { };
};