diff --git a/internal/game/logic.go b/internal/game/logic.go index 5c7f208..3cba0bc 100644 --- a/internal/game/logic.go +++ b/internal/game/logic.go @@ -23,7 +23,8 @@ const ( PlayerPlaceCooldown = 200 * time.Millisecond ) -var placeId = [10]int{blocks.Stone, blocks.Dirt, blocks.Grass, blocks.LogOak, blocks.PlanksOak, blocks.LeavesOak, blocks.Glass, blocks.DebugDir, blocks.Bedrock, blocks.Water} +var placeId = [10]int{blocks.Stone, blocks.Slab, blocks.Grass, blocks.LogOak, blocks.PlanksOak, blocks.LeavesOak, blocks.Glass, blocks.DebugDir, blocks.Bedrock, blocks.Water} +var placeAux = [10]int{0, blocks.PlanksOak, 0, 0, 0, 0, 0, 0, 0, 0} var placei = 0 var logs string @@ -297,7 +298,11 @@ func (g *Game) Update(win *glfw.Window, delta time.Duration) { } if canplace { - g.world.SetBlock(bc.Add(itype.DirectionVeci[dir]), placeId[placei], 0, nil) + aux := placeAux[placei] + if win.GetKey(glfw.KeyLeftShift) == glfw.Press { + aux = -aux + } + g.world.SetBlock(bc.Add(itype.DirectionVeci[dir]), placeId[placei], aux, nil) g.player.SetDatasetI("LastPlace", int64(g.runtime)) } } diff --git a/internal/util/minmax.go b/internal/util/minmax.go index 05edbbc..a5df348 100644 --- a/internal/util/minmax.go +++ b/internal/util/minmax.go @@ -53,3 +53,10 @@ func AbsMind(a, b float64) float64 { } return b } + +func AbsInt(x int) int { + if x < 0 { + return -x + } + return x +} diff --git a/internal/world/blocks/default.go b/internal/world/blocks/default.go index b6d95b7..b9ca615 100644 --- a/internal/world/blocks/default.go +++ b/internal/world/blocks/default.go @@ -22,6 +22,8 @@ const ( Glass + Slab + Count ) @@ -45,7 +47,9 @@ func init() { world.RegisterBlockBehaviour(13, world.BlockBehaviourStatic(world.BlockAppearance{Name: "glass", Transparent: true})) - if Count != 14 { + world.RegisterBlockBehaviour(14, SlabBehaviour{}) + + if Count != 15 { panic("world.DefaultBlocks: block count not correct (check for block numbering in default_blocks.go)") } diff --git a/internal/world/blocks/helper_appendface.go b/internal/world/blocks/helper_appendface.go index 157ff47..1886d3e 100644 --- a/internal/world/blocks/helper_appendface.go +++ b/internal/world/blocks/helper_appendface.go @@ -76,3 +76,111 @@ func appendFace(face itype.Direction, pos itype.Vec3i, texname string, faceOffse return arr } + +// same as appendFace +// faceSize is in [0, 1] +// textureSubrect is normalized, also in [0, 1]; coords start from the left-top +func appendFaceSized(face itype.Direction, pos itype.Vec3i, texname string, faceSize itype.Vec3f, faceOffset itype.Vec3f, textureSubrect itype.Rectf, arr []world.Vertex) []world.Vertex { + + switch face { + case itype.XPlus: // X+ + arr = append(arr, + // Vertex Position Normal Vector(normalized) Texture Coord Light + world.Vertex{pos.ToFloat32().Addv(1, 0, 0). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(1, faceSize[1], 0). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(1, faceSize[1], faceSize[2]). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(1, 0, 0). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(1, faceSize[1], faceSize[2]). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(1, 0, faceSize[2]). + Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 1}, 16}, + ) + case itype.XMinus: // X- + arr = append(arr, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], faceSize[2]). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], 0). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 0, faceSize[2]). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], faceSize[2]). + Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 0}, 16}, + ) + case itype.YPlus: // Y+ + arr = append(arr, + world.Vertex{pos.ToFloat32().Addv(0, 1, 0). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 1, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 1, 0). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 1, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 1, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 1, 0). + Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 0}, 16}, + ) + case itype.YMinus: // Y- + arr = append(arr, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, 0). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 0, faceSize[2]). + Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 1}, 16}, + ) + case itype.ZPlus: // Z+ + arr = append(arr, + world.Vertex{pos.ToFloat32().Addv(0, 0, 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], faceSize[1], 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, 1). + Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 1}, 16}, + ) + case itype.ZMinus: // Z- + arr = append(arr, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, faceSize[1], 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], faceSize[1], 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(0, 0, 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 1}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], faceSize[1], 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 0}, 16}, + world.Vertex{pos.ToFloat32().Addv(faceSize[0], 0, 0). + Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 1}, 16}, + ) + } + + texrect := asset.WorldTextureAtlas.RectNormalized(texname) + for i := len(arr) - 6; i < len(arr); i++ { + arr[i].Texture[0] = texrect.Left + (textureSubrect.Left+textureSubrect.Width*arr[i].Texture[0])*texrect.Width + arr[i].Texture[1] = texrect.Top + (textureSubrect.Top+textureSubrect.Height*arr[i].Texture[1])*texrect.Height + } + + return arr +} diff --git a/internal/world/blocks/slab.go b/internal/world/blocks/slab.go new file mode 100644 index 0000000..e6ed193 --- /dev/null +++ b/internal/world/blocks/slab.go @@ -0,0 +1,100 @@ +package blocks + +import ( + "edgaru089.ml/go/gl01/internal/util/itype" + "edgaru089.ml/go/gl01/internal/world" +) + +type SlabBehaviour struct{} + +func (SlabBehaviour) Static() bool { return true } +func (SlabBehaviour) RequireDataset() bool { return false } +func (SlabBehaviour) RequireBlockUpdate() bool { return false } +func (SlabBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) world.BlockAppearance { + + var hitbox itype.Boxd + if aux > 0 { // Bottom slab + hitbox = itype.Boxd{0, 0, 0, 1, 0.5, 1} + } else { // Top slab + hitbox = itype.Boxd{0, 0.5, 0, 1, 0.5, 1} + } + + return world.BlockAppearance{ + Name: "", + Transparent: true, + NotSolid: false, + Hitbox: []itype.Boxd{hitbox}, + Lookbox: []itype.Boxd{hitbox}, + + RenderType: world.CustomRendering, + CustomRenderAppend: func( + position itype.Vec3i, + aux int, + data itype.Dataset, + w *world.World, + vertexArray []world.Vertex, vertsWater []world.Vertex) (verts, waters []world.Vertex) { + + var offset itype.Vec3f + if aux < 0 { + offset = itype.Vec3f{0, 0.5, 0} + aux = -aux + } + + var name string + switch aux { + case Stone: + name = "stone" + case Sand: + name = "sand" + case PlanksOak: + name = "planks_oak" + } + + vertexArray = appendFace(itype.YMinus, position, name+".png", itype.Vec3f{0, 0, 0}.Add(offset), vertexArray) + vertexArray = appendFace(itype.YPlus, position, name+".png", itype.Vec3f{0, -0.5, 0}.Add(offset), vertexArray) + + vertexArray = appendFaceSized( + itype.XPlus, + position, + name+".png", + itype.Vec3f{1, 0.5, 1}, + itype.Vec3f{0, 0, 0}.Add(offset), + itype.Rectf{0, 0, 1, 0.5}, + vertexArray, + ) + vertexArray = appendFaceSized( + itype.XMinus, + position, + name+".png", + itype.Vec3f{1, 0.5, 1}, + itype.Vec3f{0, 0, 0}.Add(offset), + itype.Rectf{0, 0, 1, 0.5}, + vertexArray, + ) + vertexArray = appendFaceSized( + itype.ZPlus, + position, + name+".png", + itype.Vec3f{1, 0.5, 1}, + itype.Vec3f{0, 0, 0}.Add(offset), + itype.Rectf{0, 0, 1, 0.5}, + vertexArray, + ) + vertexArray = appendFaceSized( + itype.ZMinus, + position, + name+".png", + itype.Vec3f{1, 0.5, 1}, + itype.Vec3f{0, 0, 0}.Add(offset), + itype.Rectf{0, 0, 1, 0.5}, + vertexArray, + ) + + return vertexArray, vertsWater + }, + } +} +func (SlabBehaviour) BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) bool { + return false +} +func (SlabBehaviour) Break(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) {} diff --git a/internal/world/chunk.go b/internal/world/chunk.go index 0e54382..714fd15 100644 --- a/internal/world/chunk.go +++ b/internal/world/chunk.go @@ -17,7 +17,8 @@ const ( type Chunk struct { X, Z int // Chunk coordinate in global coordinate (y is always zero) - Id, Aux [ChunkSizeX][ChunkSizeY][ChunkSizeZ]uint16 + Id [ChunkSizeX][ChunkSizeY][ChunkSizeZ]uint16 + Aux [ChunkSizeX][ChunkSizeY][ChunkSizeZ]int16 // render data kept unexported (therefore excluded from gob encoding) renderChanged bool @@ -40,7 +41,7 @@ func (c *Chunk) SetChunkID(x, z int) { func (c *Chunk) SetBlock(x, y, z int, id, aux int) { c.Id[x][y][z] = uint16(id) - c.Aux[x][y][z] = uint16(aux) + c.Aux[x][y][z] = int16(aux) c.renderChanged = true switch x {