카메라의 이동 방식 2가지.
1. 카메라가 플레이어를 따라 서서히 이동하는듯한 효과의 방식.
- 카메라가 자동적으로 플레이어를 따라가는효과가있다.
- 하지만 카메라의 범위가 한계까지 이동하였을떄 화면은 끝에 멈춰있고 플레이어만 움직이는 모습을 볼 수 있다.
2. 카메라가 일정구간(맵)내에서만 이동하되, 플레이어를 따라다니며 쉬지않고 역동적으로 움직이는방식
- 플레이어의 이동 거리에 따라 비율적으로 이동하기떄문에 끊임없이 화면이 움직이는 것을 볼 수 있다.
- 플레이어가 화면의 중앙에만 위치하고자 할때는 해당기법보다는 다른 기법을 사용 해야 될 것으로 생각된다.
화면가두기. [ Utility::Saturate ]
화면 또는 카메라의 범위를 지정하여 그 범위를 넘지 않도록 조절한다.
F12로 정의를 본다면 템플릿으로 구성되어있으며 조건은
src 값이 min(미니멈)보다작다면 min(미니멈)에 고정시키고
만대로 max(맥시멈)보다크다면 max(맥시멈)으로 고정시키는 것이다.
랜더링파이프라인 수업때 이처럼 색상을 가두는 것도 했었다! (같은것은 아니지만,복습하는의미에서다시한번본다)
색상은 컬러에 X2 -1 해주는것으로 했다!
추가.
포인터 방식으로 별모양 다수의 갯수를 찍는 방법과
새로운 해제법인 SafeDelete 방식에 대하여.
Release() 함수에서 사용하며
아래와 같은 방식으로 해제 한다.
F12를 통하여 들어가 보면. define 으로 되어있으며
포인터가 해제된다면 그자리를 nullptr (0) 으로 만들어 두는 것이다.
바로윗줄에 SafeRelease(p)도 있지만 선생님께서는 SafeDelete(p)를 선호한다 하셨다.
추가. 오늘배운 프로그램 내에서 이미지 직접 수정하는 방법을 이용한 피카츄 이미지 수정해보기.
확대하면 픽셀단위로까지 보이기때문에 도트찍는 느낌으로 재미있게 수정이 가능하다.
피카츄 귀없애고 좀더 쥐처럼보이게 귀를 만들고 색을 회색으로 바꾸어 보았다.
전체코드 [접은글]
// main.h
#pragma once
#define BMAX 50
class Main : public Scene
{
private:
ObRect player;
ObCircle pet;
ObRect gaugeBar;
Bullet bullet[BMAX];
ObImage* bg;
GameObject firePos;
ObStar* stars[100]; // 포인터로 생성(새로운방식)
public:
virtual void Init() override;
virtual void Release() override; //해제
virtual void Update() override;
virtual void LateUpdate() override;//갱신
virtual void Render() override;
virtual void ResizeScreen() override;
};
// main.cpp
#include "stdafx.h"
#include "Main.h"
void Main::Init()
{
player.SetWorldPos(Vector2(0.0f, 0.0f));
player.scale = Vector2(50.0f, 50.0f);
player.rotation = 0.0f;
player.isAxis = true;
player.isVisible = true;
player.isFilled = true;
//player.pivot = Vector2(0.3f, 0.48f);
player.pivot = OFFSET_N;
player.color = Color(RANDOM->Float(), RANDOM->Float(), RANDOM->Float(), 0.5f);
pet.SetParentRT(player);
pet.SetLocalPos(Vector2(50.0f, 50.0f));
pet.scale = Vector2(20.0f, 20.0f);
pet.rotation = 0.0f;
pet.isAxis = true;
gaugeBar.SetParentT(player);
gaugeBar.pivot = OFFSET_L;
gaugeBar.SetLocalPos(Vector2(-50.0f, -70.0f));
gaugeBar.scale = Vector2(150.0f, 20.0f);
gaugeBar.color = Color(176.0f / 255.0f, 119.0f / 255.0f, 121.0f / 255.0f, 1.0f);
firePos.SetParentRT(player);
firePos.SetLocalPosY(player.scale.y * 2.0f);
firePos.scale = Vector2(50.0f, 50.0f);
firePos.isAxis = true;
bg = new ObImage(L"pikachu.jpg");
bg->scale = Vector2(4000.0f, 2800.0f);
for (int i = 0; i < 100; i++)
{
stars[i] = new ObStar(); // new 로생성한다.
// 별의 X좌표 -2000~ +2000 까지 랜덤생성
stars[i]->SetWorldPosX(RANDOM->Float(-2000.0f, 2000.0f));
// 별의 Y좌표 -1400~ +1400 까지 랜덤생성
stars[i]->SetWorldPosY(RANDOM->Float(-1400.0f, 1400.0f));
// 크기변수 scale을 만들고 30~100까지 랜덤으로 생성되도록한다.
float scale = RANDOM->Float(30.0f, 100.0f);
// 변수하나로 x,y 에 같이넣으면 랜덤으로생성된 같은숫자가 대입된다.
stars[i]->scale = Vector2(scale, scale);
// 컬러는 전부 랜덤으로
stars[i]->color = Color(RANDOM->Float(), RANDOM->Float(), RANDOM->Float(), 1.0f);
}
}
void Main::Release()
{
for (int i = 0; i < 100; i++)
{
SafeDelete(stars[i]);
// 포인터로 할당한 stars 배열들은 일반 delete 가아닌
// SafeDelete로 해제해준다!
}
}
void Main::Update()
{
cout << "mouse.x : " << INPUT->GetMouseWorldPos().x <<
" , mouse.y : " << INPUT->GetMouseWorldPos().y << endl;
//플레이어 이동
if (INPUT->KeyPress('W'))
{
player.MoveWorldPos(UP * 400.0f * DELTA);
}
else if (INPUT->KeyPress('S'))
{
player.MoveWorldPos(DOWN * 400.0f * DELTA);
}
if (INPUT->KeyPress('A'))
{
player.MoveWorldPos(LEFT * 400.0f * DELTA);
}
else if (INPUT->KeyPress('D'))
{
player.MoveWorldPos(RIGHT * 400.0f * DELTA);
}
//캠 이동
if (INPUT->KeyPress(VK_UP))
{
CAM->position += UP * 400.0f * DELTA;
}
else if (INPUT->KeyPress(VK_DOWN))
{
CAM->position += DOWN * 400.0f * DELTA;
}
if (INPUT->KeyPress(VK_LEFT))
{
CAM->position += LEFT * 400.0f * DELTA;
}
else if (INPUT->KeyPress(VK_RIGHT))
{
CAM->position += RIGHT * 400.0f * DELTA;
}
Vector2 dir = INPUT->GetMouseWorldPos() - player.GetWorldPos();
//dir.Normalize();
player.rotation = Utility::DirToRadian(dir);
player.rotation = Utility::Saturate(player.rotation, 0.0f, PI);
//ImGui::SliderAngle("Rotation", &player.rotation, 0.0f, 360.0f);
if (INPUT->KeyDown(VK_LBUTTON))
{
gaugeBar.scale.x = 0.0f;
}
if (INPUT->KeyPress(VK_LBUTTON))
{
gaugeBar.scale.x += 150.0f * DELTA;
if (gaugeBar.scale.x > 150.0f)
{
gaugeBar.scale.x = 0.0f;
}
}
//발사해라
if (INPUT->KeyUp(VK_LBUTTON))
{
for (int i = 0; i < BMAX; i++)
{
if (bullet[i].Shoot(player.GetUp(), gaugeBar.scale.x, firePos.GetWorldPos())) break;
}
}
//pet.rotation += 120.0f * ToRadian * DELTA;
pet.revolution += 60.0f * ToRadian * DELTA;
player.Update();
player.color = Color(RANDOM->Float(), RANDOM->Float(), RANDOM->Float(), 0.5f);
//pet.Update();
gaugeBar.Update();
firePos.Update();
bg->Update();
for (int i = 0; i < BMAX; i++)
{
bullet[i].Update(player);
}
for (int i = 0; i < 100; i++)
{
stars[i]->Update();
}
}
void Main::LateUpdate()
{
//CAM->position += velocity;
//CAM->position += velocity / 100.0f;
//CAM->position += velocity / 100.0f * DELTA;
//벡터를 이용한 카메라 플레이어 따라가기
//플레이어의 위치에서 카메라의 위치의 차이 벡터를 구하여
//카메라의 포지션에 초당(DELTA)로 더해준다면 플레이어가이동하면서
//카메라와의 차이가 생기는만큼 카메라는 초당이동하기때문에 따라가는 효과가능
//Vector2 velocity = player.GetWorldPos() - CAM->position;
//CAM->position += velocity * DELTA;
// 플레이어는 맵의 끝까지 이동하되
// 카메라의 위치가 화면 끝에서 가만히있지않고 조금더 역동적으로 움직이도록
// 카메라는 플레이어보다 움직이는범위가 좁게설정한다.
// 그렇게 한다면 좀더 역동적인 화면 연출이 된다.
CAM->position.x = (4000.0f - 1400.0f) * (player.GetWorldPos().x / 4000.0f);
CAM->position.y = (2800.0f - 800.0f) * (player.GetWorldPos().y / 2800.0f);
//카메라위치(x) = (맵전체가로-화면의가로) * (플레이어의 x 좌표를 / 맵의가로로 나눈다)
//카메라위치(y) = (맵전체세로-화면의세로) * (플레이어의 y 좌표를 / 맵의세로로 나눈다)
//선생님방식
CAM->position.x = player.GetWorldPos().x * (4000.0f - app.GetWidth()) / 4000.0f;
CAM->position.y = player.GetWorldPos().y * (2800.0f - app.GetHeight()) / 2800.0f;
// 플레이어 이동 범위 지정 ( X = -2000 ~ +2000 / Y = - 1400 ~ + 1400 )
// 중간과 끝에 플레이어 스케일x/2 한이유는 플레이어중점을 가운데두고 있기때문에
// 끝에서 플레이어가 스케일의반만큼이 밖으로 나가서 나가지않게 가두었음
player.SetWorldPosX(Utility::Saturate(player.GetWorldPos().x,
-2000.0f + (player.scale.x/2), 2000.0f - (player.scale.x/2)));
player.SetWorldPosY(Utility::Saturate(player.GetWorldPos().y,
-1400.0f + (player.scale.x/2), 1400.0f - (player.scale.x/2)));
// 카메라 화면 범위 지정 ( X = -2000 ~ +2000 / Y = - 1400 ~ + 1400 )
CAM->position.x = Utility::Saturate(CAM->position.x,
-2000.0f + app.GetHalfWidth(),
2000.0f - app.GetHalfWidth());
CAM->position.y = Utility::Saturate(CAM->position.y,
-1400.0f + app.GetHalfHeight(),
1400.0f - app.GetHalfHeight());
//모든 오브젝트가 이동한 뒤
for (int i = 0; i < BMAX; i++)
{
bullet[i].LateUpdate();
}
}
void Main::Render()
{
bg->Render();
for (int i = 0; i < 100; i++)
{
stars[i]->Render();
}
player.Render();
gaugeBar.Render();
//pet.Render();
//firePos.Render();
for (int i = 0; i < BMAX; i++)
{
bullet[i].Render();
}
}
void Main::ResizeScreen()
{
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR param, int command)
{
app.SetAppName(L"Game1");
app.SetInstance(instance);
app.InitWidthHeight(1400,800.0f);
WIN->Create();
Main* main = new Main();
int wParam = (int)WIN->Run(main);
SafeDelete(main);
/*delete main;
delete main;*/
WIN->Destroy();
WIN->DeleteSingleton();
return wParam;
}
'공부' 카테고리의 다른 글
[C++/DX11] - AABB 충돌 (0) | 2023.01.12 |
---|---|
[C++/DX11] - 충돌,마우스좌표 컬러벡터 (0) | 2023.01.10 |
복습 - DX11 렌더링파이프라인 (0) | 2023.01.08 |
[C++ / Dx11] 색상표 만들기 (0) | 2023.01.05 |
DX 11 - 렌더링 파이프 라인 (0) | 2023.01.03 |
댓글