큐브추가, 카메라 오빗팅 추가
This commit is contained in:
21
Content/cube.obj
Normal file
21
Content/cube.obj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
v -0.5 -0.5 0.5
|
||||||
|
v 0.5 -0.5 0.5
|
||||||
|
v 0.5 0.5 0.5
|
||||||
|
v -0.5 0.5 0.5
|
||||||
|
v -0.5 -0.5 -0.5
|
||||||
|
v 0.5 -0.5 -0.5
|
||||||
|
v 0.5 0.5 -0.5
|
||||||
|
v -0.5 0.5 -0.5
|
||||||
|
|
||||||
|
f 1 2 3
|
||||||
|
f 1 3 4
|
||||||
|
f 8 7 6
|
||||||
|
f 8 6 5
|
||||||
|
f 4 3 7
|
||||||
|
f 4 7 8
|
||||||
|
f 5 1 4
|
||||||
|
f 5 4 8
|
||||||
|
f 5 6 2
|
||||||
|
f 5 2 1
|
||||||
|
f 2 6 7
|
||||||
|
f 2 7 3
|
||||||
@@ -51,92 +51,83 @@ bool MainScene::init()
|
|||||||
auto visibleSize = _director->getVisibleSize();
|
auto visibleSize = _director->getVisibleSize();
|
||||||
auto origin = _director->getVisibleOrigin();
|
auto origin = _director->getVisibleOrigin();
|
||||||
auto safeArea = _director->getSafeAreaRect();
|
auto safeArea = _director->getSafeAreaRect();
|
||||||
auto safeOrigin = safeArea.origin;
|
|
||||||
|
|
||||||
/////////////////////////////
|
// 2. Add a menu item with "X" image, which is clicked to quit the program
|
||||||
// 2. add a menu item with "X" image, which is clicked to quit the program
|
|
||||||
// you may modify it.
|
|
||||||
|
|
||||||
// add a "close" icon to exit the progress. it's an autorelease object
|
|
||||||
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
|
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
|
||||||
AX_CALLBACK_1(MainScene::menuCloseCallback, this));
|
AX_CALLBACK_1(MainScene::menuCloseCallback, this));
|
||||||
|
|
||||||
if (closeItem == nullptr || closeItem->getContentSize().width <= 0 || closeItem->getContentSize().height <= 0)
|
if (closeItem != nullptr)
|
||||||
{
|
{
|
||||||
problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
|
float x = origin.x + visibleSize.width - closeItem->getContentSize().width / 2;
|
||||||
}
|
float y = origin.y + closeItem->getContentSize().height / 2;
|
||||||
else
|
|
||||||
{
|
|
||||||
float x = safeOrigin.x + safeArea.size.width - closeItem->getContentSize().width / 2;
|
|
||||||
float y = safeOrigin.y + closeItem->getContentSize().height / 2;
|
|
||||||
closeItem->setPosition(Vec2(x, y));
|
closeItem->setPosition(Vec2(x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create menu, it's an autorelease object
|
|
||||||
auto menu = Menu::create(closeItem, NULL);
|
auto menu = Menu::create(closeItem, NULL);
|
||||||
menu->setPosition(Vec2::ZERO);
|
menu->setPosition(Vec2::ZERO);
|
||||||
this->addChild(menu, 1);
|
this->addChild(menu, 1);
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// 3. add your codes below...
|
// 3. 3D Setup
|
||||||
|
|
||||||
|
// Grid settings
|
||||||
|
const int gridSize = 10;
|
||||||
|
const float cubeDim = 1.0f;
|
||||||
|
const float spacing = 0.1f;
|
||||||
|
const float step = cubeDim + spacing;
|
||||||
|
|
||||||
|
// Calculate center of the grid
|
||||||
|
// Grid goes from 0 to (gridSize-1)*step
|
||||||
|
float gridWidth = (gridSize - 1) * step;
|
||||||
|
Vec3 gridCenter(gridWidth / 2.0f, 0.0f, gridWidth / 2.0f);
|
||||||
|
|
||||||
// Some templates (uncomment what you need)
|
// Create 10x10 cubes using MeshRenderer and the generated cube.obj
|
||||||
_touchListener = EventListenerTouchAllAtOnce::create();
|
for (int i = 0; i < gridSize; ++i)
|
||||||
_touchListener->onTouchesBegan = AX_CALLBACK_2(MainScene::onTouchesBegan, this);
|
|
||||||
_touchListener->onTouchesMoved = AX_CALLBACK_2(MainScene::onTouchesMoved, this);
|
|
||||||
_touchListener->onTouchesEnded = AX_CALLBACK_2(MainScene::onTouchesEnded, this);
|
|
||||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);
|
|
||||||
|
|
||||||
//_mouseListener = EventListenerMouse::create();
|
|
||||||
//_mouseListener->onMouseMove = AX_CALLBACK_1(MainScene::onMouseMove, this);
|
|
||||||
//_mouseListener->onMouseUp = AX_CALLBACK_1(MainScene::onMouseUp, this);
|
|
||||||
//_mouseListener->onMouseDown = AX_CALLBACK_1(MainScene::onMouseDown, this);
|
|
||||||
//_mouseListener->onMouseScroll = AX_CALLBACK_1(MainScene::onMouseScroll, this);
|
|
||||||
//_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);
|
|
||||||
|
|
||||||
_keyboardListener = EventListenerKeyboard::create();
|
|
||||||
_keyboardListener->onKeyPressed = AX_CALLBACK_2(MainScene::onKeyPressed, this);
|
|
||||||
_keyboardListener->onKeyReleased = AX_CALLBACK_2(MainScene::onKeyReleased, this);
|
|
||||||
_eventDispatcher->addEventListenerWithFixedPriority(_keyboardListener, 11);
|
|
||||||
|
|
||||||
// add a label shows "Hello World"
|
|
||||||
// create and initialize a label
|
|
||||||
|
|
||||||
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
|
|
||||||
if (label == nullptr)
|
|
||||||
{
|
{
|
||||||
problemLoading("'fonts/Marker Felt.ttf'");
|
for (int j = 0; j < gridSize; ++j)
|
||||||
|
{
|
||||||
|
auto cube = MeshRenderer::create("cube.obj");
|
||||||
|
if (cube)
|
||||||
|
{
|
||||||
|
cube->setPosition3D(Vec3(i * step, 0.0f, j * step));
|
||||||
|
cube->setCameraMask((unsigned short)CameraFlag::USER1);
|
||||||
|
this->addChild(cube);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// position the label on the center of the screen
|
|
||||||
label->setPosition(
|
|
||||||
Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - label->getContentSize().height));
|
|
||||||
|
|
||||||
// add the label as a child to this layer
|
// Setup Camera for Quarter View (Isometric-like)
|
||||||
|
_camera3D = Camera::createPerspective(60.0f, visibleSize.width / visibleSize.height, 0.1f, 1000.0f);
|
||||||
|
_camera3D->setCameraFlag(CameraFlag::USER1);
|
||||||
|
|
||||||
|
// Initial camera position setup
|
||||||
|
_targetPos = gridCenter;
|
||||||
|
_pitch = 45.0f;
|
||||||
|
_yaw = 45.0f;
|
||||||
|
_distance = 25.0f;
|
||||||
|
updateCameraPosition();
|
||||||
|
|
||||||
|
this->addChild(_camera3D);
|
||||||
|
|
||||||
|
// Mouse Listener
|
||||||
|
_mouseListener = EventListenerMouse::create();
|
||||||
|
_mouseListener->onMouseMove = AX_CALLBACK_1(MainScene::onMouseMove, this);
|
||||||
|
_mouseListener->onMouseUp = AX_CALLBACK_1(MainScene::onMouseUp, this);
|
||||||
|
_mouseListener->onMouseDown = AX_CALLBACK_1(MainScene::onMouseDown, this);
|
||||||
|
_mouseListener->onMouseScroll = AX_CALLBACK_1(MainScene::onMouseScroll, this);
|
||||||
|
_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);
|
||||||
|
|
||||||
|
// Disable the default 2D camera for these 3D objects by using CameraFlag::USER1
|
||||||
|
// The label and menu will use the default camera (CameraFlag::DEFAULT)
|
||||||
|
|
||||||
|
// Add a label for confirmation
|
||||||
|
auto label = Label::createWithTTF("10x10 Cube Grid", "fonts/Marker Felt.ttf", 24);
|
||||||
|
if (label)
|
||||||
|
{
|
||||||
|
label->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - 30));
|
||||||
this->addChild(label, 1);
|
this->addChild(label, 1);
|
||||||
}
|
}
|
||||||
// add "HelloWorld" splash screen"
|
|
||||||
auto sprite = Sprite::create("HelloWorld.png"sv);
|
|
||||||
if (sprite == nullptr)
|
|
||||||
{
|
|
||||||
problemLoading("'HelloWorld.png'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// position the sprite on the center of the screen
|
|
||||||
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
|
|
||||||
|
|
||||||
// add the sprite as a child to this layer
|
|
||||||
this->addChild(sprite, 0);
|
|
||||||
auto drawNode = DrawNode::create();
|
|
||||||
drawNode->setPosition(Vec2(0, 0));
|
|
||||||
addChild(drawNode);
|
|
||||||
|
|
||||||
drawNode->drawRect(safeArea.origin + Vec2(1, 1), safeArea.origin + safeArea.size, Color4F::BLUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduleUpdate() is required to ensure update(float) is called on every loop
|
|
||||||
scheduleUpdate();
|
scheduleUpdate();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -169,31 +160,75 @@ void MainScene::onTouchesEnded(const std::vector<ax::Touch*>& touches, ax::Event
|
|||||||
bool MainScene::onMouseDown(Event* event)
|
bool MainScene::onMouseDown(Event* event)
|
||||||
{
|
{
|
||||||
EventMouse* e = static_cast<EventMouse*>(event);
|
EventMouse* e = static_cast<EventMouse*>(event);
|
||||||
// AXLOGD("onMouseDown detected, button: {}", static_cast<int>(e->getMouseButton()));
|
if (e->getMouseButton() == EventMouse::MouseButton::BUTTON_LEFT)
|
||||||
|
{
|
||||||
|
_isMouseDown = true;
|
||||||
|
_lastMousePos = e->getLocationInView();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainScene::onMouseUp(Event* event)
|
bool MainScene::onMouseUp(Event* event)
|
||||||
{
|
{
|
||||||
EventMouse* e = static_cast<EventMouse*>(event);
|
EventMouse* e = static_cast<EventMouse*>(event);
|
||||||
AXLOGD("onMouseUp detected, button: {}", static_cast<int>(e->getMouseButton()));
|
if (e->getMouseButton() == EventMouse::MouseButton::BUTTON_LEFT)
|
||||||
|
{
|
||||||
|
_isMouseDown = false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainScene::onMouseMove(Event* event)
|
bool MainScene::onMouseMove(Event* event)
|
||||||
{
|
{
|
||||||
EventMouse* e = static_cast<EventMouse*>(event);
|
EventMouse* e = static_cast<EventMouse*>(event);
|
||||||
// AXLOGD("onMouseMove detected, X:{} Y:{}", e->getLocation().x, e->getLocation().y);
|
Vec2 currentPos = e->getLocationInView();
|
||||||
|
|
||||||
|
if (_isMouseDown)
|
||||||
|
{
|
||||||
|
Vec2 delta = currentPos - _lastMousePos;
|
||||||
|
float sensitivity = 0.15f; // 감도 조절 (기존 0.5f에서 하향)
|
||||||
|
|
||||||
|
_yaw += delta.x * sensitivity;
|
||||||
|
_pitch += delta.y * sensitivity; // 마우스 이동 방향에 맞춰 상하 각도 변경
|
||||||
|
|
||||||
|
// Clamp pitch to avoid flipping (수직 방향 각도 제한)
|
||||||
|
_pitch = std::clamp(_pitch, 10.0f, 85.0f);
|
||||||
|
|
||||||
|
updateCameraPosition();
|
||||||
|
}
|
||||||
|
_lastMousePos = currentPos;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainScene::onMouseScroll(Event* event)
|
bool MainScene::onMouseScroll(Event* event)
|
||||||
{
|
{
|
||||||
EventMouse* e = static_cast<EventMouse*>(event);
|
EventMouse* e = static_cast<EventMouse*>(event);
|
||||||
// AXLOGD("onMouseScroll detected, X:{} Y:{}", e->getScrollX(), e->getScrollY());
|
float zoomSensitivity = 0.5f; // 줌 감도 조절
|
||||||
|
_distance -= e->getScrollY() * zoomSensitivity;
|
||||||
|
|
||||||
|
// Clamp distance
|
||||||
|
_distance = std::clamp(_distance, 5.0f, 100.0f);
|
||||||
|
|
||||||
|
updateCameraPosition();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainScene::updateCameraPosition()
|
||||||
|
{
|
||||||
|
if (!_camera3D) return;
|
||||||
|
|
||||||
|
// Convert spherical coordinates to Cartesian
|
||||||
|
float pitchRad = AX_DEGREES_TO_RADIANS(_pitch);
|
||||||
|
float yawRad = AX_DEGREES_TO_RADIANS(_yaw);
|
||||||
|
|
||||||
|
float x = _distance * cosf(pitchRad) * cosf(yawRad);
|
||||||
|
float y = _distance * sinf(pitchRad);
|
||||||
|
float z = _distance * cosf(pitchRad) * sinf(yawRad);
|
||||||
|
|
||||||
|
_camera3D->setPosition3D(_targetPos + Vec3(x, y, z));
|
||||||
|
_camera3D->lookAt(_targetPos, Vec3(0, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void MainScene::onKeyPressed(EventKeyboard::KeyCode code, Event* event)
|
void MainScene::onKeyPressed(EventKeyboard::KeyCode code, Event* event)
|
||||||
{
|
{
|
||||||
AXLOGD("Scene: #{} onKeyPressed, keycode: {}", _sceneID, static_cast<int>(code));
|
AXLOGD("Scene: #{} onKeyPressed, keycode: {}", _sceneID, static_cast<int>(code));
|
||||||
|
|||||||
@@ -65,10 +65,21 @@ public:
|
|||||||
~MainScene() override;
|
~MainScene() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateCameraPosition();
|
||||||
|
|
||||||
GameState _gameState = GameState::init;
|
GameState _gameState = GameState::init;
|
||||||
ax::EventListenerTouchAllAtOnce* _touchListener = nullptr;
|
ax::EventListenerTouchAllAtOnce* _touchListener = nullptr;
|
||||||
ax::EventListenerKeyboard* _keyboardListener = nullptr;
|
ax::EventListenerKeyboard* _keyboardListener = nullptr;
|
||||||
ax::EventListenerMouse* _mouseListener = nullptr;
|
ax::EventListenerMouse* _mouseListener = nullptr;
|
||||||
int _sceneID = 0;
|
int _sceneID = 0;
|
||||||
|
|
||||||
|
// Camera Orbit State
|
||||||
|
ax::Camera* _camera3D = nullptr;
|
||||||
|
ax::Vec3 _targetPos = ax::Vec3::ZERO;
|
||||||
|
float _pitch = 45.0f; // degrees
|
||||||
|
float _yaw = 45.0f; // degrees
|
||||||
|
float _distance = 25.0f;
|
||||||
|
bool _isMouseDown = false;
|
||||||
|
ax::Vec2 _lastMousePos = ax::Vec2::ZERO;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user