1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* GATE PROJECT LICENSE:
+----------------------------------------------------------------------------+
| Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at>                 |
| All rights reserved.                                                       |
|                                                                            |
| Redistribution and use in source and binary forms, with or without         |
| modification, are permitted provided that the following conditions are met:|
|                                                                            |
| 1. Redistributions of source code must retain the above copyright notice,  |
|    this list of conditions and the following disclaimer.                   |
| 2. Redistributions in binary form must reproduce the above copyright       |
|    notice, this list of conditions and the following disclaimer in the     |
|    documentation and/or other materials provided with the distribution.    |
|                                                                            |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE    |
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR        |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF       |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS   |
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN    |
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)    |
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF     |
| THE POSSIBILITY OF SUCH DAMAGE.                                            |
+----------------------------------------------------------------------------+
*/
#include "gamemodule.hpp"
#include "gate/arrays.hpp"
#include "gate/maps.hpp"
#include "gate/times.hpp"

namespace gate
{
    namespace apps
    {

        class GATE_API_LOCAL BlockLevelsGame : public GameModule
        {
        public:
            class World
            {
            public:
                World(index_t x_length, index_t y_width, index_t z_height);

                void set(index_t x, index_t y, index_t z, char block);
                char get(index_t x, index_t y, index_t z) const;

                char operator()(index_t x, index_t y, index_t z) const;

                index_t Length() const;
                index_t Width() const;
                index_t Height() const;

            private:
                index_t length;
                index_t width;
                index_t height;
                ArrayList<char> buffer;

                char* getBlockPtr(index_t x, index_t y, index_t z) const;
            };

            enum BlockType
            {
                Block_Empty,
                Block_Dirt,
                Block_OakPlanks,
                Block_Oak,
                Block_OakLeaves,
                Block_Cobble,
                Block_Grass,
                Block_Brick,
                Block_Stone,
                Block_StoneBrick,

                Block_Start1
            };

            enum BlockTextureType
            {
                BlockTexture_Dirt,
                BlockTexture_Cobblestone,
                BlockTexture_GrassTop,
                BlockTexture_GrassSide,
                BlockTexture_OakPlanks,
                BlockTexture_OakSide,
                BlockTexture_OakTop,
                BlockTexture_OakLeaves,
                BlockTexture_Brick,
                BlockTexture_Stone,
                BlockTexture_StoneBrick,
            };

            BlockLevelsGame();
            virtual ~BlockLevelsGame() noexcept;

            virtual void	loadModule(GlSurface& surface);<--- Function in derived class
            virtual void	unloadModule(GlSurface& surface);<--- Function in derived class
            virtual void	render(GlSurface& surface);<--- Function in derived class
            virtual void	processKeyDown(Keyboard::KeyEnum key, uint32_t state);<--- Function in derived class
            virtual void	processKeyUp(Keyboard::KeyEnum key, uint32_t state);<--- Function in derived class
            virtual void	processPointerDown(real32_t x, real32_t y, real32_t xMax, real32_t yMax);<--- Function in derived class
            virtual void	processPointerMove(real32_t x, real32_t y, real32_t xMax, real32_t yMax);<--- Function in derived class
            virtual void	processPointerUp(real32_t x, real32_t y, real32_t xMax, real32_t yMax);<--- Function in derived class

            struct GATE_API_LOCAL Cuboid
            {
                Vertex	point;
                Vertex	dim;
                Color	border;
                Color	fill;
                void* textures[6];	// sides 1 - 4, top, bottom
                uint8_t	side_bits;

                inline Cuboid(Vertex const& pnt = Vertex(), Vertex const& dimension = Vertex(), Color const& borderCol = Color(), Color const& fillCol = Color())
                    : point(pnt), dim(dimension), border(borderCol), fill(fillCol), side_bits(0xff)
                {
                    gate_mem_clear(this->textures, sizeof(this->textures));
                }
                inline Cuboid(Vertex const& pnt, Vertex const& dimension, void* const* texture_ids, size_t texture_count)
                    : point(pnt), dim(dimension), border(0, 0, 0, 0), fill(0, 0, 0, 0), side_bits(0)
                {
                    gate_mem_clear(this->textures, sizeof(this->textures));
                    if (texture_count >= 6)
                    {
                        for (size_t n = 0; n != 6; ++n)
                        {
                            this->textures[n] = texture_ids[n];
                        }
                    }
                    else if (texture_count >= 3)
                    {
                        for (size_t n = 0; n != 4; ++n)
                        {
                            this->textures[n] = texture_ids[0];
                        }
                        this->textures[4] = texture_ids[1];
                        this->textures[5] = texture_ids[2];
                    }
                    else if (texture_count >= 2)
                    {
                        for (size_t n = 0; n != 4; ++n)
                        {
                            this->textures[n] = texture_ids[0];
                        }
                        this->textures[4] = texture_ids[1];
                        this->textures[5] = texture_ids[1];
                    }
                    else if (texture_count == 1)
                    {
                        for (size_t n = 0; n != 6; ++n)
                        {
                            this->textures[n] = texture_ids[0];
                        }
                    }
                    else
                    {
                        gate_mem_clear(&textures[0], sizeof(textures));
                    }

                    for (size_t n = 0; n != 6; ++n)
                    {
                        if (this->textures[n])
                        {
                            side_bits |= static_cast<uint8_t>(1 << n);
                        }
                    }
                }
            };

            struct BlockTextures
            {
                void* textures[6];
            };

            struct Block
            {
                BlockType	type;
                Vertex		point;
                uint8_t		side_bits;

                inline Block(BlockType bt = Block_Empty, Vertex const& pnt = Vertex(), uint8_t sides = 1)
                    : type(bt), point(pnt), side_bits(sides)
                {

                }
            };

        private:
            void		addCuboid(Vertex point, Vertex dimension, Color borderColor, Color fillColor);
            void		addCuboid(Vertex point, Vertex dimension, void* const* texture_id, size_t texture_count);

            void		addBlock(BlockType type, Vertex const& point, uint8_t side_bits);

            void		renderBlock(GlApi& gl, BlockType type, Vertex point, uint8_t side_bits);
            void		renderBlock(GlApi& gl, Vertex const& point, BlockTextureType const* textypes, size_t texcount, uint8_t side_bits);

            char		getBlockId(real32_t x, real32_t y, real32_t z);
            bool		isSolidBlock(char blockId);
            bool		isSolidBlock(real32_t x, real32_t y, real32_t z);

            void		move(real32_t addX, real32_t addY);
            void		checkFloor();


            static void renderQuadArea(GlApi& gl, Vertex const& p1, Vertex const& p2, Vertex const& p3, Vertex const& p4, Color const& col);
            static void renderQuadBorders(GlApi& gl, Vertex const& p1, Vertex const& p2, Vertex const& p3, Vertex const& p4, Color const& col);
            static void renderQuadTexture(GlApi& gl, Vertex const& p1, Vertex const& p2, Vertex const& p3, Vertex const& p4, void* texture);
            static void	renderCuboid(GlApi& gl, Cuboid const& cuboid);

        private:
            typedef ArrayList<Cuboid>		CuboidList;
            typedef ArrayList<Block>		BlockList;
            typedef Map<intptr_t, void*>	TextureMap;
            typedef Map<BlockType, BlockTextures>	BlockTextureMap;

            CuboidList	cuboids;
            TextureMap	textures;
            BlockTextureMap	blockTextures;
            BlockList		blocks;

            real32_t	x;
            real32_t	y;
            real32_t	z;
            real32_t	direction;			// rad from x to y (counter-clockwise)
            real32_t	moveVelocity;		// units per second
            real32_t	strafeVelocity;		// direction movement patch angle in rad from x to y to move (counter-clockwise)
            real32_t	angularVelocity;	// rad per second from x to y (counter-clockwise)
            World		loadedWorld;
            TimeCounter	timer;

        private:
            static World createWorld(size_t x_length = 64, size_t y_width = 64, size_t z_height = 64);
            static void loadObjectMapIntoWorld(World& world, index_t x, index_t y, index_t z, char const* const* const* objectLevels);

        };

    }	//	end of namespace apps
}	//	end of namespace gate