Axiom3D写游戏:用Overlay实现Mesh浏览.

  从网上找了些资源,大多搜Ogre,Mesh资源,然后为了方便查看各个Mesh,以及对应骨骼动画.为了实用性,考虑放在原游戏窗口里实现.最开始打算窗口新建viewport来实现,后发现这种方式的局限性,不新键窗口与场景管理,所有的viewport都是对应的同一场景,不同的viewport能改变的是摄像机,这种比较容易实现如赛车游戏右下角添加一个viewport,里面显示从车的后视镜看到的情景,因为是同一场景,不同的摄像角度.后面考虑新键窗口,不同的窗口使用不同的场景管理,刚开始发现可行,后面发现有个问题,就是出在Overlay上,因为Overlay是独立与场景,视图,窗口这些,因此你新建的窗口也是共享对应的Overlay层,这样窗口显示同样的Overlay,也可以设置独立场景关闭Overlay显示,处理起来应该可行,但是会麻烦些.

  综合之上,我决定在原窗口之上加一个Overlay来实现.下面是效果图.

  图片缩小与压缩后,显示的有点不清楚.主要功能有查看当前程序内所有Mesh,在Mesh View内能够缩放,旋转对应Mesh,自动检测是否包含骨骼动画,能够显示对应各种动画,总的来说,我们是用了熟悉Ogre里相应的Overlay的实现.下面给出上面这个效果用到的Overlay文件,其中相应代码如下:

template container BorderPanel(meshView/main)
{
    metrics_mode relative
    material SdkTrays/MiniTray
    left 0.1
    width 0.8
    top 0.1
    height 0.8
    uv_coords 0.4 0.4 0.6 0.6

    border_material SdkTrays/MiniTextBox
    border_size 0.008 0.008 0.01 0.01
    border_topleft_uv     0.0 0.0 0.4 0.4
    border_top_uv         0.4 0.0 0.6 0.4
    border_topright_uv    0.6 0.0 1.0 0.4
    border_left_uv        0.0 0.4 0.4 0.6
    border_right_uv       0.6 0.4 1.0 0.6
    border_bottomleft_uv  0.0 0.6 0.4 1.0
    border_bottom_uv      0.4 0.6 0.6 1.0
    border_bottomright_uv 0.6 0.6 1.0 1.0

    container BorderPanel(viewMesh)
    {
        #SdkTrays/Tray
        material SdkTrays/Bands
        metrics_mode relative
        uv_coords 0.1 0.1 0.9 0.9
        left 0.18
        width 0.6
        top 0.02
        height 0.76

        border_material SdkTrays/Tray
        border_size 0.01 0.01 0.01 0.01
        border_topleft_uv     0.000 0.000 0.375 0.375
        border_top_uv         0.375 0.000 0.625 0.375
        border_topright_uv    0.625 0.000 1.000 0.375
        border_left_uv        0.000 0.375 0.375 0.625
        border_right_uv       0.625 0.375 1.000 0.625
        border_bottomleft_uv  0.000 0.625 0.375 1.000
        border_bottom_uv      0.375 0.625 0.625 1.000
        border_bottomright_uv 0.625 0.625 1.000 1.000
    }
}

template container BorderPanel(meshView/listBox)
{
    material SdkTrays/Frame
    metrics_mode relative
    uv_coords 0.375 0.375 0.625 0.625
    left 0.02
    width 0.15
    top 0.02
    height 0.4

    border_material SdkTrays/Frame
    border_size 0.01 0.01 0.01 0.01
    border_topleft_uv     0.000 0.000 0.375 0.375
    border_top_uv         0.375 0.000 0.625 0.375
    border_topright_uv    0.625 0.000 1.000 0.375
    border_left_uv        0.000 0.375 0.375 0.625
    border_right_uv       0.625 0.375 1.000 0.625
    border_bottomleft_uv  0.000 0.625 0.375 1.000
    border_bottom_uv      0.375 0.625 0.625 1.000
    border_bottomright_uv 0.625 0.625 1.000 1.000

    container BorderPanel(meshScroll)
    {
        metrics_mode relative
        material SdkTrays/ScrollTrack
        width 0.01
        horz_align right
        left -0.018
        top 0.01
        height 0.38
        uv_coords 0.0 0.31 1.0 0.69

        border_material SdkTrays/ScrollTrack
        border_size 0 0 0.01 0.01
        border_top_uv    0.0 0.0 1.0 0.31
        border_bottom_uv 0.0 0.69 1.0 1.0

        element Panel(meshDrag)
        {
            metrics_mode relative
            material SdkTrays/Handle
            horz_align center
            top 0.01
            left -0.005
            width 0.01
            height 0.02
        }
    }
}

# text item
 template container BorderPanel(meshTextItem)
{
    material SdkTrays/MiniTextBox
    metrics_mode relative
    height 0.04
    width 0.12
    top 0.01
    left 0.007
    uv_coords 0.4 0.4 0.6 0.6

    border_material SdkTrays/MiniTextBox
    border_size 0.005 0.005 0.01 0.01
    border_topleft_uv     0.0 0.0 0.4 0.4
    border_top_uv         0.4 0.0 0.6 0.4
    border_topright_uv    0.6 0.0 1.0 0.4
    border_left_uv        0.0 0.4 0.4 0.6
    border_right_uv       0.6 0.4 1.0 0.6
    border_bottomleft_uv  0.0 0.6 0.4 1.0
    border_bottom_uv      0.4 0.6 0.6 1.0
    border_bottomright_uv 0.6 0.6 1.0 1.0

    element TextArea(text)
    {
        metrics_mode relative
        left 0.006
        top 0.01
        font_name SdkTrays/Caption
        char_height 0.02
        space_width 0.005
        colour 0 0 0
        caption Special Delivery
    }
}

meshview.overlay

  里面的东东不多也不复杂,在说明这个文件作用,我们先看下Overlay相应类的各个方法与属性.

  OveralyElement比较重要,相应的属性是子类都用的比较多的.对应的left,top,width,height对应的是0-1的小数(如left=0.1 top=0.1,整个视图宽高为1000*800,则left与top对应的像素位置是100,80这里).而前缀带pixel(pixelLeft,pixelTop,pixelWidth,pixHeight)是对应的像素点,这个好理解.带前缀derived只有left与top,这二个属性是在整个视图里的位置,前面的left,top是针对父元素的位置.对应头字母大写(Left,Top,Width,Height)的是根据MatricsMode不同给出对应的像素长度或是0-1的对应位置.默认的MetricsMode是Relative模式(0-1).而Pixel就是像素点模式.

  OveralyElementContainer在OveralyElement基础上,增加功能可以添加OveralyElement元素.

  OveralyElementManager用来管理OveralyElement与OveralyElementContainer所有对象,以及对应OveralyElement的创建,对应OveralyElement的销毁需要用这个类来DestroyElement来处理,不然在这个里面还会保留,当你新增加同名元素时,就会出错.

  Overaly这个类组合当前所需要的OveralyElement以及子类对象,处理统一缩放,旋转,大小,FindVisibleObjects负责处理相应对象是否加到渲染列表,也就是说,只有当OveralyElement元素及子类对象放入Overaly,才能渲染到窗口.

  OveralyManager实现了接口IScriptLoader,则有分析一种脚本的能力,对应的就是.overlay脚本.相关分析代码也在这个类里.对应Overlay的创建与删除也在这个类里.

  OveralyElement实现了IRenderable接口,意思可渲染的,但是和OveralyElementContainer对象一样,相应的渲染没有任何数据,对应的有三个子类,分别是TextAre,Panel,BorderPanel,这三个类里会实现填充接口里的RenderOperation.(注意这里只说可渲染,如果要加到渲染列表中,需要通过Overaly才能实现,前面介绍Overaly时有提到.)

  在介绍下面类之前,说下Overaly里相关元素都是二D的,声明一个长方形只需要指定对角二个点就行,那么同理声明下面各独立元素的纹理坐标时,只需要指定左上角与右下角二点,在对应文件里的顺序分别是u1,v1,u2,v2.UV的指只能指定0到1的浮点数.

  TextAre我开始还以为最容易,那想不是,通过Initialize里,我们知道对应每个输出元素分别是P3T2C1,就是顶点三个float,纹理坐标二个float,一个float表示颜色,因为颜色不容易变化,故顶点与纹理放一个buffer,颜色单独放一个buffer.输出时填充根据字符串长度确定输出顶点个数.填充每个顶点位置与纹理位置.

  Panel比较简单,数据BUFF里每个元素就三个顶点,只有在不透明及设置了纹理,才会添加到渲染列表里,在有纹理的情况下,添加纹理坐标声明及buffer,可以添加多层纹理.

  BorderPanel在Panel的基础上添加了边框,在这里,边框不是指一个,也不是四个,而是八个,大家想下,把一个立方体横竖各二刀,一共是九块,除开中间那个由Panel输出,余下8块全属于边框,就是BorderPanel负责渲染的.各个边框再当一个Panel来看,剩下问题不大,余下都是针对各个边框大小,位置的更改.

  好了,Overlay相关类介绍完了,回到最开始的需求,我们需要一个显示的展示mesh的位置,一个存放所有mesh名字的地方,一个对应mesh所有骨骼动画名字的地方.我想这个界面能够和像素无关,所以选择的是MetricMode模式是relative.

  对应我们的需求与上面的实现的Overlay代码,第一部分是BorderPanel模式meshView/main,主要包含主界面以及里面的mesh展示窗口,BorderPanel的border_size控制边框大小,对应的八个窗口的uv控制着对应纹理的截取面积,使用BorderPanel一般有二种情况比较明显,一种是material与border_material不同,那么就会有一个border_material样式的边框,更常见的是material与border_material使用相同的材质,这种材质边角有透明元素使得边角圆滑,控制border_size与对应八个窗口的UV,能改变圆滑形状.注意border_size的大小不影响子元素在其中的位置.

  而存放mesh与动画我们模拟winForm里的listBox,一个边框,以及可能显示在右边的拖动条,拖动条上有个元素表示当前位置.相应元素分别对应BorderPanel(meshView/listBox),BorderPanel(meshScroll),Panel(meshDrag).

  listBox里存放的item用模板BorderPanel(meshTextItem)表示,主要包含一个边框与一个文本.

  下面给出相关ViewListBox的相关代码.

namespace BS.Game
{
    public delegate void SelectItemChangedHandler(string value);
    public class ViewListBox : IMouseEventListener
    {
        public BorderPanel ListBox { get; set; }
        public event SelectItemChangedHandler SelectItemChanged;

        private BorderPanel menuScroll;
        private Panel meshDrag;

        private int meshCount;
        private int maxIndex;
        private int currentIndex;
        private string selectItem;

        private List<string> texts;
        private Dictionary<string, BorderPanel> items = new Dictionary<string, BorderPanel>();

        public ViewListBox(string name, float left, float top)
        {
            OverlayManager om = OverlayManager.Instance;
            this.ListBox = om.Elements.CreateElementFromTemplate("meshView/listBox", "BorderPanel", name) as BorderPanel;
            this.menuScroll = this.ListBox.Children[this.ListBox.Name + "/meshScroll"] as BorderPanel;
            this.meshDrag = this.menuScroll.Children[this.menuScroll.Name + "/meshDrag"] as Panel;

            this.ListBox.Top = top;
            this.ListBox.Left = left;

            this.menuScroll.Height = this.ListBox.Height - 0.07f;

            this.MouseOrder = 101;
            InputManger.Instance.AddMouseListener(this);
        }

        public void Load(List<string> names)
        {
            if (items != null && items.Count > 0)
            {
                foreach (var kv in items)
                {
                    kv.Value.NukeOverlayElement();
                }
                items.Clear();
            }

            OverlayManager om = OverlayManager.Instance;

            float top = 0.01f;
            texts = names;
            meshCount = texts.Count;
            maxIndex = (int)((this.ListBox.Height - 0.03) / 0.04);
            string name = this.ListBox.Name + "/meshItem";
            bool bScroll = meshCount > maxIndex;
            for (int index = 0; index < meshCount; index++)
            {
                string meshName = names[index];
                var meshItem = om.Elements.CreateElementFromTemplate("meshTextItem", "BorderPanel", name + index) as BorderPanel;
                var textAre = meshItem.Children[meshItem.Name + "/text"] as TextArea;
                textAre.Text = meshName;
                items.Add(meshName, meshItem);
                if (index <= maxIndex)
                {
                    meshItem.Top = top;
                    meshItem.IsVisible = true;
                    meshItem.Width = bScroll ? this.ListBox.Width - 0.03f : this.ListBox.Width - 0.014f;
                    this.ListBox.AddChild(meshItem);
                    top = top + meshItem.Height;
                }
                else
                {
                    meshItem.IsVisible = false;
                    this.ListBox.AddChild(meshItem);
                }
            }
            menuScroll.IsVisible = bScroll;
        }

        public void OnMouseDown(object sender, Axiom.Input.MouseEventArgs args)
        {
            foreach (var kv in items)
            {
                if (kv.Value.IsCursorOver(args.X, args.Y))
                {
                    //slectMeshLoad(kv.Key);
                    if (SelectItemChanged != null)
                    {
                        selectItem = kv.Key;
                        kv.Value.BorderMaterialName = "SdkTrays/MiniTextBox/Over";
                        kv.Value.MaterialName = "SdkTrays/MiniTextBox/Over";
                        SelectItemChanged(kv.Key);
                    }
                    break;
                }
            }
        }

        public void OnMouseUp(object sender, Axiom.Input.MouseEventArgs args)
        {

        }

        public void OnMouseMove(object sender, MouseMoveArgs args)
        {
            foreach (var kv in items)
            {
                if (kv.Key == selectItem)
                    continue;
                if (kv.Value.IsCursorOver(args.X, args.Y))
                {
                    kv.Value.BorderMaterialName = "SdkTrays/MiniTextBox/Over";
                    kv.Value.MaterialName = "SdkTrays/MiniTextBox/Over";
                }
                else
                {
                    kv.Value.BorderMaterialName = "SdkTrays/MiniTextBox";
                    kv.Value.MaterialName = "SdkTrays/MiniTextBox";
                }
            }
        }

        public void OnMouseWheelChanged(object sender, MouseWheelArgs args)
        {
            if (!this.ListBox.IsCursorOver(InputManger.Instance.X, InputManger.Instance.Y))
                return;
            if (meshCount > maxIndex)
            {
                if (args.Delta > 0)
                    currentIndex--;
                else
                    currentIndex++;
            }
            ScrollShow();
        }

        public void ScrollShow()
        {
            if (maxIndex >= meshCount)
                return;

            currentIndex = Math.Min(currentIndex, meshCount - maxIndex - 1);
            currentIndex = Math.Max(0, currentIndex);

            float top = 0.01f;
            for (int i = 0; i < meshCount; i++)
            {
                string meshName = texts[i];
                var meshItem = items[meshName];

                if (i >= currentIndex && i <= currentIndex + maxIndex)
                {
                    meshItem.IsVisible = true;
                    meshItem.Width = this.ListBox.Width - 0.03f;
                    meshItem.Top = top;
                    top = top + meshItem.Height;
                }
                else
                {
                    meshItem.IsVisible = false;
                }
            }
            meshDrag.Top = 0.01f + currentIndex * this.menuScroll.Height / (meshCount - maxIndex);
        }

        public int MouseOrder { get; set; }
    }
}

ViewListBox

  在ViewListBox里,初始化我们只需要生成的名字,左上角的位置,Load根据传进来的集合生成对应的TextItem项,点击则引发事件,鼠标滑动引发判断应该显示那些项.整个过程还是比较简单的.

  下面是MeshView的相关代码.

    public class MeshView : IMouseEventListener
    {
        public const string name = "meshView";
        public const string entityName = "MeshViewEntity";

        private Overlay mainLayer;
        private OverlayElementContainer meshMain;
        private BorderPanel view;
        private ViewListBox selectListBox;
        private ViewListBox animationListBox;

        private SceneNode meshNode;
        private AnimationState animationState;

        public MeshView()
        {
            OverlayManager om = OverlayManager.Instance;
            string nameBase = name + "/";

            this.mainLayer = om.Create(nameBase + "main");
            this.meshMain = om.Elements.CreateElementFromTemplate("meshView/main", "BorderPanel", name) as OverlayElementContainer;
            this.view = this.meshMain.Children[nameBase + "viewMesh"] as BorderPanel;
            this.selectListBox = new ViewListBox("meshListBox", 0.02f, 0.02f);
            this.selectListBox.SelectItemChanged += slectMeshLoad;
            this.meshMain.AddChild(selectListBox.ListBox);

            LoadMeshNames();

            this.mainLayer.ZOrder = 310;
            this.mainLayer.AddElement(this.meshMain);

            this.MouseOrder = 100;
            InputManger.Instance.AddMouseListener(this);
        }

        public bool IsVisible
        {
            get
            {
                return mainLayer.IsVisible;
            }
        }

        public void Show()
        {
            if (mainLayer.IsVisible)
                mainLayer.Hide();
            else
                mainLayer.Show();
        }

        public void LoadMeshNames()
        {
            var meshNames = ResourceGroupManager.Instance.GetResourceNames(".mesh")
                .Where(p => p.EndsWith(".mesh")).ToList();
            OverlayManager om = OverlayManager.Instance;

            this.selectListBox.Load(meshNames);
        }

        private void slectMeshLoad(string meshName)
        {
            string entityName = "MeshViewEntity";
            var scene = Root.Instance.SceneManager;
            if (meshNode != null)
            {
                scene.DestroySceneNode(meshNode);
                scene.RemoveEntity(entityName);
            }

            meshNode = scene.RootSceneNode.CreateChildSceneNode(new Vector3(0, 0, 0), Quaternion.Identity);
            var entity = scene.CreateEntity(entityName, meshName);
            float lenght = entity.BoundingBox.Size.Length * 2;
            //scene
            meshNode.Translate(new Vector3(lenght / 10.0f, 0f, -1.0f * lenght));
            //在所有物体显示之上 针对overlay
            entity.RenderQueueGroup = RenderQueueGroupID.Count;
            //关掉深度检测 针对场景里的entity
            foreach (Material sub in entity.SubEntityMaterials)
            {
                // sub.DepthCheck = false;
            }

            meshNode.AttachObject(entity);
            if (entity.HasSkeleton)
            {
                List<string> animationNames = new List<string>();
                foreach (var animat in entity.Skeleton.Animations)
                {
                    animationNames.Add(animat.Name);
                }
                if (animationListBox == null)
                {
                    animationListBox = new ViewListBox("animationListBox", 0.02f, 0.43f);
                    animationListBox.ListBox.Height = 0.35f;
                    animationListBox.SelectItemChanged += seletAnimation;
                    this.meshMain.AddChild(animationListBox.ListBox);
                }
                animationListBox.ListBox.IsVisible = true;
                animationListBox.Load(animationNames);
            }
            else
            {
                if (animationListBox != null)
                {
                    animationListBox.ListBox.IsVisible = false;
                }
            }
            this.mainLayer.AddElement(meshNode);
        }

        private void seletAnimation(string name)
        {
            if (meshNode != null)
            {
                Entity entity = meshNode.GetObject(entityName) as Entity;
                if (entity != null)
                {
                    animationState = entity.GetAnimationState(name);
                    animationState.IsEnabled = true;
                    animationState.Loop = true;
                }
            }
        }

        public void OnMouseDown(object sender, Axiom.Input.MouseEventArgs args)
        {

        }

        public void OnMouseUp(object sender, Axiom.Input.MouseEventArgs args)
        {

        }

        public void OnMouseMove(object sender, MouseMoveArgs args)
        {
            if (InputManger.Instance.IsMousePressed(MouseButtons.Left))
            {
                if (meshNode != null)
                {
                    this.meshNode.Yaw((Real)(new Degree((Real)(args.RelativeX * 0.15f))));
                    this.meshNode.Pitch((Real)(new Degree((Real)(args.RelativeY * 0.15f))));
                }
            }
        }

        public int MouseOrder
        {
            get;
            set;
        }

        public void OnMouseWheelChanged(object sender, MouseWheelArgs args)
        {
            if (meshNode != null && this.view.IsCursorOver(InputManger.Instance.X, InputManger.Instance.Y))
            {
                var offest = args.Delta * Math.Abs(args.Value) / 2;
                meshNode.Translate(new Vector3(offest / 10, 0, offest));
            }
        }

        public void Update(float timeSinceLastFrame)
        {
            //deltaTime += timeSinceLastFrame;
            if (animationState != null)
            {
                animationState.Time += timeSinceLastFrame;
            }
        }
    }

MeshView

  几个扩展方法.

namespace BS.Game
{
    public static class Helper
    {
        public static bool IsCursorOver(this OverlayElement element, Vector2 pos)
        {
            return IsCursorOver(element, pos.x, pos.y);
        }

        public static bool IsCursorOver(this OverlayElement element, float x, float y)
        {
            if (element.MetricsMode == MetricsMode.Relative)
            {
                var oMgr = OverlayManager.Instance;
                x = x / oMgr.ViewportWidth;
                y = y / oMgr.ViewportHeight;
            }
            if (element.IsVisible)
            {
                if (x >= element.DerivedLeft && x <= element.DerivedLeft + element.Width &&
                    y >= element.DerivedTop && y <= element.DerivedTop + element.Height)
                {
                    return true;
                }
            }

            return false;
        }

        public static void NukeOverlayElement(this OverlayElement element)
        {
            var container = element as OverlayElementContainer;
            if (container != null)
            {
                var toDelete = new List<OverlayElement>();
                foreach (OverlayElement child in container.Children.Values)
                {
                    toDelete.Add(child);
                }

                for (int i = 0; i < toDelete.Count; i++)
                {
                    NukeOverlayElement(toDelete[i]);
                }
            }
            if (element != null)
            {
                OverlayElementContainer parent = element.Parent;
                if (parent != null)
                {
                    parent.RemoveChild(element.Name);
                }
                OverlayManager.Instance.Elements.DestroyElement(element.Name);
            }
        }
    }
}

Helper

  需要注意的是selectMeshLoad这个方法,原本scene.DestroySceneNode这个方法一直不得行,我后面查找对应的Ogre源码,发现freeTempVertexBufferMap 是multimap类型,因为我修改HardwareBufferManagerBase里freeTempVertexBufferMap从字典修改为可以重复键值的,然后修改一些引用的地方,因调用scene.DestroySceneNode而引发的健值重复问题才消失,运行一段时间在任务管理里查看了下,内存没有增加,这个问题暂时就这样放着,相关问题我提到http://axiom3d.net/forums/viewtopic.php?f=1&t=1523&start=0.

  在selectMeshLoad里加载对应的mesh时,需要注意mesh有大有小,我们需要根据相应Entity的大小来改变node的Z值,注意我们显示的时候,左边一块是用来放ViewListBox的,所以我们需要移动相应Node的X值.如代码里,我们根据视角,当前窗口确定大致的XZ位置,后面查看各Mesh时可以发现这个方法一般能正常显示在正确的位置.

  注意selectMeshLoad里二句注释的位置,大家可以调整下这二句代码是否启用,查看效果.作用比较大.然后查看是否有骨骼动画,加载骨骼动画.

  对应事件都比较简单,鼠标move控制节点旋转,使我们可以各个角度查看Mesh.鼠标滑轮滚动则是调整Mesh的缩放.Update更新骨骼动画.

  附件就不放了,因为主要代码都在上面,并且相应的Axiom里源代码我改动了一些,这些附件太多,上传太要时间.

  

  

  

时间: 2024-12-09 12:19:35

Axiom3D写游戏:用Overlay实现Mesh浏览.的相关文章

Axiom3D写游戏:第一个窗口

Axiom主要的代码大致翻看了下,就想到了自己来模拟一下游戏开发. 这章主要包括创建窗口及3D渲染的一些基本元素,并添加一个第三人称的骨骼动画作主角,加上前文中修改过后的地形组件,能用鼠标和键盘进行漫游.如下图所示. 在Axiom上给出的例子中,可以选择是用OpenGL或是DirectX渲染,现在有问题的地方是如果用OpenGL渲染,而Axiom鼠标与键盘输入采用的是SharpInputSystem,这个在DirectX渲染下是没有问题的,但是在OpenGL渲染的窗口下得不到正确的鼠标位置.而D

有个非计算机专业的问我:怎么学写游戏?

下面是我的回答: 1.游戏分为不同的平台类型:网页游戏.移动端的手机游戏.PC端游戏.专用主机游戏,作为个人开发者,基本上只有第二种能够赚钱,第一种需要服务器端的运营,后2种就不用考虑了 2.写游戏用什么软件工具?简单的说来,就两个:2D的用Cocos-2D,3D的用Unity 3D.且它们都有一个好处:可以直接跨平台部署到Android/iPhone上去(甚至网页端). 3.但关键的问题是:你需要一个好的创意! 这个创意不仅仅是可玩性,也要有一定核心技术,别人没法轻易模仿的.比如PSP上我印象

为什么不用C++写游戏(这些工作,QT都替开发者解决了,C++没有根类导致太多的问题,也没有字符串类)

当今世界上绝大多数游戏都是C++写的,为什么要说不呢? 要做什么?写游戏. 写游戏首先要考虑些什么?做什么样的游戏,图形.音效.游戏逻辑如何实现. 用C++要先考虑什么?定义跨平台数据类型抽象,实现常用集合类,设计宏实现RTTI,写一个支持Unicode并可以和其他多种字符串类型互相转换的字符串类,自定义内存分配器,写个shared_ptr,组织预编译头文件,设计实现Object基类以处理跨DLL内存管理等问题…… 那么这些和做游戏有什么关系?不做好这些就很难开始写游戏. 做这些要话多少时间?很

python写游戏运维管理后台

最近在用python写游戏运维管理的后台,待功能完善后放源码,大致功能如下: 有兴趣的可以加我一起来做.

代写android编程作业、代写游戏作业

代写android编程作业.代写游戏作业功能要求分析该游戏要实现的功能描述如下: 关于:可以让玩家了解游戏的一些开发信息等. 帮助:可以让玩家了解游戏的相关玩法,学会如何玩这个游戏. 开始游戏:点击可以进入游戏界面,开始玩游戏. 设置:设置游戏中音乐和音效的开关状态.退出:退出游戏. 练习模式:玩家与系统之间的对战,利用android重力感应让乒乓球进行移动. 对战模式:玩家与玩家之间的对战,利用android重力感应让乒乓球进行移动. 另外,该游戏设计流程主要分三个阶段. 第一个阶段是游戏登录

腾讯高级工程师:如何从头开始写游戏服务器框架_转

转自: 腾讯高级工程师:如何从头开始写游戏服务器框架 本文作者:韩伟,腾讯互娱高级工程师,目前在 Next 产品中心研发创新类型游戏. 前言:从去年开始作者投入了一些具体游戏项目的开发,这些新的游戏项目,比较接近独立游戏的开发方式.在这个过程中,作者从头写了一个游戏服务器端的框架,以便获得更好的开发效率和灵活性.因此这篇文章便是该项目服务器框架的设计和实现过程的总结. PS:框架的基本运行环境是 Linux ,采用 C++ 编写.为了能在各种环境上运行和使用,采用了 gcc4.8 这个“古老”的

2015/11/1用Python写游戏,pygame入门(1):pygame的安装

这两天学习数据结构和算法,有时感觉并不如直接做项目来的有趣.刚刚学完python的基本使用,现在刚好趁热打铁做个小项目. 由于本人一直很想制作一款游戏,就想使用Python制作一个基础的游戏.搜了一下资料,看到一个很便于使用的库,也就是pygame. pygame介绍 pygame是一个建立在SDL(Simple DirectMedia Layer)上的Python模块,是一个跨平台模块.SDL是用C写的,也可以用C++开发,也有很多语言,pygame就是一个Python中使用的库. 安装pyg

2015/11/7用Python写游戏,pygame入门(7):碰撞检测

我们已经完成了飞机大战的大部分东西,但是游戏还是没有办法正式开玩,因为子弹并不能打掉飞机.只有完成了这一个工作,游戏才算基本成型. 今天的内容就非常简单了,就是做到这个碰撞检测,以及控制好子弹和飞机的消失.pygame里的sprite模块里有碰撞检测部分,但是,我们这里自己动手实现一个碰撞检测的函数. 检测碰撞的方法很简单,就是子弹的位置在飞机图片的内部.由于子弹和飞机的速度比较快,所以不需要非常精确地判别. 我们认为,如果子弹的坐标(b.x, b.y)在飞机的图片范围内,也就是(e.x, e,

2015/11/6用Python写游戏,pygame入门(6):控制大量的对象

昨天我们已经实现了这个游戏的三个基本类. 但是现在它还是没办法做成一个适合玩的游戏,毕竟只有一架敌机的游戏是很乏味的.所以,我们需要好多子弹,也需要好多敌机. 所以,我们要创建list,这个list存放Bullet或者Enemy的实例. 以Bullet为例: bullet = [] #创建子弹 for i in range(6): bullet.append(Bullet()) ... for b in bullet:#移动子弹 b.move(time_passed_second) ... fo