跟着cherno手搓游戏引擎【10】使用glm窗口特性

这篇具有很好参考价值的文章主要介绍了跟着cherno手搓游戏引擎【10】使用glm窗口特性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

修改ImGui层架构:

创建:

跟着cherno手搓游戏引擎【10】使用glm窗口特性,游戏引擎

ImGuiBuild.cpp:引入ImGui

#include"ytpch.h"
#define IMGUI_IMPL_OPENGL_LOADER_GLAD//opengl的头文件需要的定义,说明使用的是gald
#include "backends/imgui_impl_opengl3.cpp"
#include "backends/imgui_impl_glfw.cpp"

Layer.h:加入GuiRender方法,每次渲染Gui都会调用

#pragma once
#include"YOTO/Core.h"
#include"YOTO/Event/Event.h"
namespace YOTO {
	class YOTO_API Layer
	{
	public:
		Layer(const std::string& name = "Layer");
		virtual ~Layer();
		virtual void OnAttach(){}
		virtual void OnDetach() {}
		virtual void OnUpdate() {}
		virtual void OnImGuiRender() {}// 每层都可以拥有自己的UI窗口
		virtual void OnEvent(Event& event) {}
		inline const std::string& GetName() const { return m_DebugName; }
	protected:
		std::string m_DebugName;
	};

}

ImGuiLayer.h:删除冗余部分,仅留下加入,删除,和Render方法,添加Begine和End,用于每次刷新UI的配置和删除UI。

#pragma once
#include"YOTO/Layer.h"
#include"YOTO/Event/KeyEvent.h"
#include"YOTO/Event/MouseEvent.h"
#include"YOTO/Event/ApplicationEvent.h"
namespace YOTO {

	class YOTO_API ImGuiLayer:public Layer
	{
	public:
		ImGuiLayer();
		~ImGuiLayer();
		virtual void OnAttach()override;
		virtual void OnDetach()override;
		virtual void OnImGuiRender()override; 
		void Begin();
		void End();
	private:
		float m_Time = 0.0f;
	};
}

ImGuiLayer.cpp:删除原来的Update,把配置、绘制UI的代码、渲染分离

#include"ytpch.h"
#include"ImGuiLayer.h"

#include"YOTO/Application.h"

#include<GLFW/glfw3.h>
#include<glad/glad.h>

#define IMGUI_IMPL_API
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
namespace YOTO {
	ImGuiLayer::ImGuiLayer()
	:Layer("ImGuiLayer") {

	}
	ImGuiLayer::~ImGuiLayer() {

	}
	void ImGuiLayer::OnAttach()
	{
		// 不需要手动写ImGui的键值对应GLFW的键值、ImGui接收GLFW窗口事件,ImGui自动完成
	   // 设置Gui配置
		IMGUI_CHECKVERSION();
		ImGui::CreateContext();
		ImGuiIO& io = ImGui::GetIO(); (void)io;
		io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;       // 启用键盘控制
		//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      //启用手柄控制
		io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;           // 启用自动布局
		io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;         //启用多视窗/平台视窗(也就是能走出Opengl绘制的框子)
		//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
		//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;

		// 设置Gui配置样式
		ImGui::StyleColorsDark();
		//ImGui::StyleColorsClassic();
		// 当viewport被启用时,我们调整windowwround /WindowBg,使平台窗口看起来与常规窗口相同。
		ImGuiStyle& style = ImGui::GetStyle();
		if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
		{
			style.WindowRounding = 0.0f;
			style.Colors[ImGuiCol_WindowBg].w = 1.0f;
		}

		Application& app = Application::Get();
		GLFWwindow* window = static_cast<GLFWwindow*>(app.GetWindow().GetNativeWindow());

		//设置平台/渲染器绑定
		ImGui_ImplGlfw_InitForOpenGL(window, true);
		ImGui_ImplOpenGL3_Init("#version 410");

	
	}
	void ImGuiLayer::OnDetach()
	{
		ImGui_ImplOpenGL3_Shutdown();
		ImGui_ImplGlfw_Shutdown();
		ImGui::DestroyContext();
	}
	void ImGuiLayer::OnImGuiRender()
	{
		static bool show = true;
		ImGui::ShowDemoWindow(&show);// 当前OnImGuiRender层显示DemoUI窗口
	}

	void ImGuiLayer::Begin()
	{
		ImGui_ImplOpenGL3_NewFrame();
		ImGui_ImplGlfw_NewFrame();
		ImGui::NewFrame();
	}

	void ImGuiLayer::End()
	{
		ImGuiIO& io = ImGui::GetIO();
		Application& app = Application::Get();
		io.DisplaySize = ImVec2(app.GetWindow().GetWidth(), app.GetWindow().GetHeight());
		// Rendering
		ImGui::Render();
		ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
		//如果启动启用多视窗/平台视窗
		if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
		{
			GLFWwindow* backup_current_context = glfwGetCurrentContext();
			ImGui::UpdatePlatformWindows();
			ImGui::RenderPlatformWindowsDefault();
			glfwMakeContextCurrent(backup_current_context);
		}
	}

	
}

LayerStack.h:修改m_LayerInsertIndex:

#pragma once
#include"Layer.h"

namespace YOTO {
	class  YOTO_API LayerStack
	{
	public:
		LayerStack();
		~LayerStack();

		void PushLayer(Layer* layer);
		void PushOverlay(Layer* layer);
		void PopLayer(Layer* layer);
		void PopOverlay(Layer* layer);

		std::vector<Layer*>::iterator begin() { return m_Layers.begin(); }
		std::vector<Layer*>::iterator end() { return m_Layers.end(); }

	private:
		std::vector<Layer*>m_Layers;
		unsigned int m_LayerInsertIndex=0;
	};

}

LayerStack.cpp: 修改PushLayer:

#include "ytpch.h"
#include "LayerStack.h"
namespace YOTO {
	LayerStack::LayerStack() {
	}
	LayerStack::~LayerStack() {
		for (Layer* layer : m_Layers)
			delete layer;
	}
	//普通push在队列最左(查找时候性能更优)
	void LayerStack::PushLayer(Layer* layer) {
		// emplace在vector容器指定位置之前插入一个新的元素。返回插入元素的位置
		// 插入 1 2 3,vector是 3 2 1
		 m_Layers.emplace(m_Layers.begin()+ m_LayerInsertIndex, layer);
		 m_LayerInsertIndex++;
	}
	//在最右插入
	void LayerStack::PushOverlay(Layer* overlay) {
		//m_LayerInsert = m_Layers.begin();//如果报错,则把这个注释取消
		m_Layers.emplace_back(overlay);
	}
	//查找
	void LayerStack::PopLayer(Layer* layer) {
		auto it = std::find(m_Layers.begin(), m_Layers.end(), layer);
		if (it != m_Layers.end()) {
			m_Layers.erase(it);
			m_LayerInsertIndex--;	// 指向Begin
		}
	}
	void LayerStack::PopOverlay(Layer* overlay) {
		auto it = std::find(m_Layers.begin(), m_Layers.end(), overlay);
		if (it != m_Layers.end())
			m_Layers.erase(it);
	}
}

Application.h:在APP中添加Gui层,无需在Sandbox中手动添加:

#pragma once
#include"Core.h"
#include"Event/Event.h"
#include"Event/ApplicationEvent.h"
#include "YOTO/Window.h"
#include"YOTO/LayerStack.h"
#include"YOTO/ImGui/ImGuiLayer.h"
namespace YOTO {
	class YOTO_API Application
	{
	public:
		Application();
		virtual ~Application();
		void Run();
		void OnEvent(Event &e);
		void PushLayer(Layer* layer);
		void PushOverlay(Layer* layer);

		inline static Application& Get() {return * s_Instance;}
		inline Window& GetWindow() { return *m_Window; }
	private:
		bool  OnWindowClosed(WindowCloseEvent& e);
		std::unique_ptr<Window>  m_Window;
		ImGuiLayer *  m_ImGuiLayer;
		bool m_Running = true;
		LayerStack m_LayerStack;
		
		static Application* s_Instance;
	};
	//在客户端定义
	Application* CreateApplication();
}

Application.cpp:在构造函数中newImGuiLayer然后Push到最后

#include"ytpch.h"
#include "Application.h"

#include"Log.h"
#include<glad/glad.h>
#include"Input.h"


namespace YOTO {
#define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)

	 Application* Application::s_Instance = nullptr;

	Application::Application() {

		YT_CORE_ASSERT(!s_Instance, "Application需要为空!")
		s_Instance = this;
		//智能指针
		m_Window = std::unique_ptr<Window>(Window::Creat());
		//设置回调函数
		m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));
		//new一个Layer,放在最后层进行渲染
		m_ImGuiLayer = new ImGuiLayer();
		PushOverlay(m_ImGuiLayer);  
		//unsigned int id;
		//glGenBuffers(1, &id);
	}
	Application::~Application() {

	}
	/// <summary>
	/// 所有的Window事件都会在这触发,作为参数e
	/// </summary>
	/// <param name="e"></param>
	void Application::OnEvent(Event& e) {
		//根据事件类型绑定对应事件
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));
		//输出事件信息
		YT_CORE_INFO("Application:{0}",e);
		for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {
			(*--it)->OnEvent(e);
			if (e.m_Handled)
				break;
		}
	}

	bool Application::OnWindowClosed(WindowCloseEvent& e) {
		m_Running = false;
		return true;
	}
	void Application::Run() {
		WindowResizeEvent e(1280, 720);
		if (e.IsInCategory(EventCategoryApplication)) {
			YT_CORE_TRACE(e);
		}
		if (e.IsInCategory(EventCategoryInput)) {
			YT_CORE_ERROR(e);
		}

		while (m_Running)
		{
			glClearColor(1,0,1,1);
			glClear(GL_COLOR_BUFFER_BIT);

			for (Layer* layer : m_LayerStack) {
				layer->OnUpdate();
			}
			//将ImGui的刷新放到APP中,与Update分开
			m_ImGuiLayer->Begin();
			
			for (Layer* layer : m_LayerStack) {
				layer->OnImGuiRender();
			}
			m_ImGuiLayer->End();
			m_Window->OnUpdate();
		}
	}
	void Application::PushLayer(Layer* layer) {
		m_LayerStack.PushLayer(layer);
		layer->OnAttach();
	}
	void Application::PushOverlay(Layer* layer) {
		m_LayerStack.PushOverlay(layer);
		layer->OnAttach();
	}
}

SandboxApp.cpp:把PushImgGui的哪行代码删掉:

#include<YOTO.h>
#include "imgui/imgui.h"
#include<stdio.h>
//#include <glm/vec3.hpp> // glm::vec3
//#include <glm/vec4.hpp> // glm::vec4
//#include <glm/mat4x4.hpp> // glm::mat4
//#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
//glm::mat4 camera(float Translate, glm::vec2 const& Rotate)
//{
//	glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.f);
//	glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate));
//	View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
//	View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
//	glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
//	return Projection * View * Model;
//}

class ExampleLayer:public YOTO::Layer
{
public:
	ExampleLayer()
	:Layer("Example") {
		//auto cam=camera(5.0f,{0.5f,0.5f});

	}
	void OnImGuiRender() override {
		ImGui::Begin("Test");
		ImGui::Text("Test");
		ImGui::End();
	}
	void OnUpdate()override {
		//YT_CLIENT_INFO("测试update");
		if (YOTO::Input::IsKeyPressed(YT_KEY_TAB)) {
			YT_CLIENT_INFO("ExampleLayerOnUpdate:TAB按下了");
		}
	}
	void OnEvent(YOTO::Event& event)override {
		if (event.GetEventType() == YOTO::EventType::KeyPressed) {
		YOTO:: KeyPressedEvent& e = (YOTO::KeyPressedEvent&)event;
		YT_CLIENT_TRACE("ExampleLayer:{0}",(char)e.GetKeyCode());
		if (e.GetKeyCode()==YT_KEY_TAB) {
			YT_CLIENT_INFO("ExampleLayerOnEvent:TAB按下了");
		}
		}
		//YT_CLIENT_TRACE("SandBoxApp:测试event{0}", event);
	}

private:

};


class Sandbox:public YOTO::Application
{
public:
	Sandbox() {
		PushLayer(new ExampleLayer());
		//PushLayer(new YOTO::ImGuiLayer());
	}
	~Sandbox() {

	}

private:

};

YOTO::Application* YOTO::CreateApplication() {
	printf("helloworld");
	return new Sandbox();
}

作业:

src下的premake5.lua:修改sandbox的includedirs加入"YOTOEngine/vendor"

workspace "YOTOEngine"		-- sln文件名
	architecture "x64"	
	configurations{
		"Debug",
		"Release",
		"Dist"
	}
startproject "Sandbox"
-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
-- 组成输出目录:Debug-windows-x86_64
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
-- 包含相对解决方案的目录
IncludeDir={}
IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include"
IncludeDir["Glad"]="YOTOEngine/vendor/Glad/include"
IncludeDir["ImGui"] ="YOTOEngine/vendor/imgui"
IncludeDir["glm"] ="YOTOEngine/vendor/glm"
--项目中包含某包
include "YOTOEngine/vendor/GLFW"
include "YOTOEngine/vendor/Glad"
include "YOTOEngine/vendor/imgui"

project "YOTOEngine"		--YOTOEngine项目
	location "YOTOEngine"--在sln所属文件夹下的YOTOEngine文件夹
	kind "SharedLib"--dll动态库
	language "C++"
	targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录
	objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录

	staticruntime "Off"

	pchheader "ytpch.h"
	pchsource "YOTOEngine/src/ytpch.cpp"
	-- 包含的所有h和cpp文件
	files{
		"%{prj.name}/src/**.h",
		"%{prj.name}/src/**.cpp",
		"%{prj.name}/vendor/glm/glm/**.hpp",
		"%{prj.name}/vendor/glm/glm/**.inl"
	}
	-- 包含目录
	includedirs{
		"%{prj.name}/src",
		"%{prj.name}/vendor/spdlog-1.x/include",
		"%{IncludeDir.GLFW}",
		"%{IncludeDir.Glad}",
		"%{IncludeDir.ImGui}",
		"%{IncludeDir.glm}"
	}
	links{
		"GLFW",-- GLFW.lib库链接到YOTOEngine项目中
		"Glad",-- Glad.lib库链接到YOTOEngine项目中
		"ImGui",-- ImGui.lib库链接到YOTOEngine项目中
		"opengl32.lib"
	}
	-- 如果是window系统
	filter "system:windows"
		cppdialect "C++17"
		-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;
		-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
		systemversion "latest"	-- windowSDK版本
		-- 预处理器定义
		defines{
			"YT_PLATFORM_WINDOWS",
			"YT_BUILD_DLL",
			-- "YT_ENABLE_ASSERTS",
			"GLFW_INCLUDE_NONE"-- 让GLFW不包含OpenGL
		}
		-- 编译好后移动Hazel.dll文件到Sandbox文件夹下
		postbuildcommands{
			("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")
		}
	-- 不同配置下的预定义不同
	filter "configurations:Debug"
		defines "YT_DEBUG"
		runtime "Debug"
		symbols "On"

	filter "configurations:Release"
		defines "YT_RELEASE"
		runtime "Release"
		optimize "On"

	filter "configurations:Dist"
		defines "YT_DIST"
		runtime "Release"
		optimize "On"

project "Sandbox"
	location "Sandbox"
	kind "ConsoleApp"
	language "C++"
	staticruntime "Off"
	targetdir ("bin/" .. outputdir .. "/%{prj.name}")
	objdir ("bin-int/" .. outputdir .. "/%{prj.name}")

	files{
		"%{prj.name}/src/**.h",
		"%{prj.name}/src/**.cpp"
	}
	-- 同样包含spdlog头文件
	includedirs{
		"YOTOEngine/vendor/spdlog-1.x/include",
		"YOTOEngine/src",
		"YOTOEngine/vendor",
		"%{IncludeDir.glm}"
	}
	-- 引用YOTOEngine
	links{
		"YOTOEngine",
		"GLFW",
		"opengl32.lib"
	}

	filter "system:windows"
		cppdialect "C++17"
		systemversion "latest"

		defines{
			"YT_PLATFORM_WINDOWS"
		}

	filter "configurations:Debug"
		defines "YT_DEBUG"
		runtime "Debug"
		symbols "On"

	filter "configurations:Release"
		defines "YT_RELEASE"
		runtime "Release"
		optimize "On"

	filter "configurations:Dist"
		defines "YT_DIST"
		runtime "Release"
		optimize "On"

 vendor/ImGui的premake5.la添加    defines { "IMGUI_API=__declspec(dllexport)" }

project "ImGui"
	kind "StaticLib"
	language "C++"
    staticruntime "off"

	targetdir ("bin/" .. outputdir .. "/%{prj.name}")
	objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
	defines { "IMGUI_API=__declspec(dllexport)" }
	files
	{
		"imconfig.h",
		"imgui.h",
		"imgui.cpp",
		"imgui_draw.cpp",
		"imgui_internal.h",
		"imgui_tables.cpp",
		"imgui_widgets.cpp",
		"imstb_rectpack.h",
		"imstb_textedit.h",
		"imstb_truetype.h",
		"imgui_demo.cpp"
	}

	filter "system:windows"
		systemversion "latest"
		cppdialect "C++17"

	filter "system:linux"
		pic "On"
		systemversion "latest"
		cppdialect "C++17"

	filter "configurations:Debug"
		runtime "Debug"
		symbols "on"

	filter "configurations:Release"
		runtime "Release"
		optimize "on"

    filter "configurations:Dist"
		runtime "Release"
		optimize "on"
        symbols "off"

测试:

点dockspace

跟着cherno手搓游戏引擎【10】使用glm窗口特性,游戏引擎

点出来几个窗口随便摆摆:

跟着cherno手搓游戏引擎【10】使用glm窗口特性,游戏引擎

 能拖出去:跟着cherno手搓游戏引擎【10】使用glm窗口特性,游戏引擎文章来源地址https://www.toymoban.com/news/detail-823105.html

到了这里,关于跟着cherno手搓游戏引擎【10】使用glm窗口特性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 跟着cherno手搓游戏引擎【6】ImGui和ImGui事件

    下载链接: GitHub - TheCherno/imgui: Dear ImGui: Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies  新建文件夹,把下载好的文件放入对应路径:  SRC下的premake5.lua文件:添加ImGui 在Platform下创建OpenGl,将imgui_impl_opengl3.cpp和.h加入到该文件夹。 并且更名: 150行改为:

    2024年01月17日
    浏览(40)
  • 跟着cherno手搓游戏引擎【8】按键和鼠标的KeyCode

    先把glfw3.h里的KeyCode的定义抄到咱这里来。 在YOTO下创建KeyCode.h:  MouseButtonCodes.h:和KeyCode.h一样作用,把GLFW改成自己的 YOTO.h: SandboxApp.cpp:在ExampleLayer测试轮询和KeyCode  明日继续更新数学和ImGui停靠和视口

    2024年01月18日
    浏览(32)
  • 如何使用现代C++特性构建游戏引擎

    游戏引擎是用来设计、开发和构建计算机游戏的软件框架。它们由一些基本的工具和程序构成,可帮助游戏设计师和开发者轻松地创建、管理和优化游戏。基本上,游戏引擎是实现游戏的所有技术的一个集合。 现代C++(指C++11、C++14和C++17)为游戏引擎的开发提供了强大的功能

    2024年02月05日
    浏览(46)
  • Hazel游戏引擎(011)窗口抽象和GLFW创建窗口

    文中若有代码、术语等错误,欢迎指正 此节目的 为了有窗口效果,但不想使用原生的window32写起,所以用glfw窗口库。 也为了完成008计划事件系统的 创建窗口 部分 图示 添加glfw子模块 修改premake 解决方案下的premake修改 效果 目前类图 Application类可以调用创建窗口函数,而窗

    2024年02月13日
    浏览(35)
  • Games104现代游戏引擎学习笔记10

    Physics Actors and Shapes Actor Static:静态actor,例如挡板等 Actor Dynamic:动态actor,例如可移动的箱子 Trigger:触发器 Actor-Kinematic:违背物理原则,由设计决定,不遵循真实物理原则 反物理物体容易导致很多数学运算出现问题 Triangle Meshes一般只允许静态物体使用 Height Fields通常用于地

    2024年02月11日
    浏览(47)
  • C#开发的OpenRA游戏之建造物品的窗口10

    前面已经分析完成建造物品的过程,从物品进入队列,直到物品按时间进行生产完成。那么生产完成之后,又是怎么样放置到游戏的地图里面的呢?本文就来分析这个问题。 前面可以看到,当物品建造完成时,会在右边的面板上显示建造完成: 在上面显示Ready的文字。这时候

    2024年02月12日
    浏览(43)
  • cocos游戏引擎--cocos creater2.4.10

    新建项目 打开其他项目 在 Dashboard 中,打开 新建项目 选项卡,选中 Hello World 项目模板。js   资源管理器 Scene 场景编辑器 Node Tree 层级管理器 属性检查器(Properties) 控件库 控制台(Console) 最左边选择预览窗口的比例大小,来模拟在不同移动设备上的显示效果 Rotate 按钮决

    2024年01月24日
    浏览(53)
  • 【游戏】PC游戏引擎简介及游戏使用技术检测技巧

    从事游戏安全行业多年,各种游戏引擎让人眼花缭乱,对游戏分析肯定也想了解相关引擎特点,这样才能更好的进行下一步的分析。 今天就将PC上常见的引擎及作品进行介绍,并介绍一些工具去快速了解一个新游戏。 先看一个steam上游戏引擎统计数据 https://steamdb.info/tech/。

    2024年02月07日
    浏览(61)
  • 【算法】游戏中的学习,使用c#面向对象特性控制游戏角色移动

    最近,小悦的生活像是一首繁忙的交响曲,每天忙得团团转,虽然她的日程安排得满满当当,但她并未感到充实。相反,她很少有时间陪伴家人,这让她感到有些遗憾。在周五的午后,小悦的哥哥突然打来电话,他的声音里充满了焦虑。 “小悦,我有个事情想拜托你。”哥哥

    2024年02月08日
    浏览(53)
  • 使用团结引擎开发Unity 3D射击游戏

           本案例是初级案例,意在引导想使用unity的初级开发者能较快的入门,体验unity开发的方便性和简易性能。       本次我们将使用团结引擎进行开发,帮助想体验团结引擎的入门开发者进行较快的环境熟悉。      本游戏是一个俯视角度的射击游戏。主角始终位于屏幕

    2024年01月19日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包