Initial commit
This commit is contained in:
commit
0245a5cb43
22 changed files with 610 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/tetris
|
||||||
6
Makefile
Normal file
6
Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
GO = go
|
||||||
|
|
||||||
|
.PHONY: tetris
|
||||||
|
|
||||||
|
tetris :
|
||||||
|
$(GO) build -o $@
|
||||||
23
README.md
Normal file
23
README.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Tetris in golang
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- [x] Initial Commit - Project Scaffolding (rendering engine)
|
||||||
|
- [ ] 0.1 - Grid
|
||||||
|
- [ ] 0.2 - Basic shapes (falling + collision with floor)
|
||||||
|
- [ ] 0.3 - Shapes: Lock + spawn
|
||||||
|
- [ ] 0.4 - Collision with with blocks in grid
|
||||||
|
- [ ] 0.5 - left/right movement
|
||||||
|
- [ ] 0.6 - Shapes rotation
|
||||||
|
- [ ] 0.7 - Soft Drop
|
||||||
|
- [ ] 0.8 - Clear lines
|
||||||
|
- [ ] 0.9 - Score
|
||||||
|
- [ ] 0.10 - Next shape
|
||||||
|
- [ ] 0.11 - RNG Shape generation
|
||||||
|
- [ ] 0.12 - Sound
|
||||||
|
- [ ] 0.13 - State machine: Menu, Gameplay and Game Over screen.
|
||||||
|
- [ ] 1.0 - Bugfixes
|
||||||
|
|
||||||
|
## Future things (aka Rad stuffs!)
|
||||||
|
|
||||||
|
- [ ] Animations (Clear lines)
|
||||||
55
assets/def.go
Normal file
55
assets/def.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
"tetris/engine/graphics/font"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed sprites.png
|
||||||
|
var Sprite []byte
|
||||||
|
|
||||||
|
var Font = font.TileFont{
|
||||||
|
Charmap: map[rune]byte{
|
||||||
|
'a': 0x20,
|
||||||
|
'b': 0x21,
|
||||||
|
'c': 0x22,
|
||||||
|
'd': 0x23,
|
||||||
|
'e': 0x24,
|
||||||
|
'f': 0x25,
|
||||||
|
'g': 0x26,
|
||||||
|
'h': 0x27,
|
||||||
|
'i': 0x28,
|
||||||
|
'j': 0x29,
|
||||||
|
'k': 0x2a,
|
||||||
|
'l': 0x2b,
|
||||||
|
'm': 0x2c,
|
||||||
|
'n': 0x30,
|
||||||
|
'o': 0x31,
|
||||||
|
'p': 0x32,
|
||||||
|
'q': 0x33,
|
||||||
|
'r': 0x34,
|
||||||
|
's': 0x35,
|
||||||
|
't': 0x36,
|
||||||
|
'u': 0x37,
|
||||||
|
'v': 0x38,
|
||||||
|
'w': 0x39,
|
||||||
|
'x': 0x3a,
|
||||||
|
'y': 0x3b,
|
||||||
|
'z': 0x3c,
|
||||||
|
'0': 0x40,
|
||||||
|
'1': 0x41,
|
||||||
|
'2': 0x42,
|
||||||
|
'3': 0x43,
|
||||||
|
'4': 0x44,
|
||||||
|
'5': 0x45,
|
||||||
|
'6': 0x46,
|
||||||
|
'7': 0x47,
|
||||||
|
'8': 0x48,
|
||||||
|
'9': 0x49,
|
||||||
|
'.': 0x4a,
|
||||||
|
'-': 0x4b,
|
||||||
|
'"': 0x4c,
|
||||||
|
},
|
||||||
|
CaseInsensitive: true,
|
||||||
|
}
|
||||||
BIN
assets/sprite.xcf
Normal file
BIN
assets/sprite.xcf
Normal file
Binary file not shown.
BIN
assets/sprites.png
Normal file
BIN
assets/sprites.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
41
engine/graphics/font/tilefont.go
Normal file
41
engine/graphics/font/tilefont.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package font
|
||||||
|
|
||||||
|
import (
|
||||||
|
"tetris/engine/graphics"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TileFont represents a tile-based font where each character maps
|
||||||
|
// to a tile location (X, Y) in a tileset or texture atlas.
|
||||||
|
//
|
||||||
|
// The character-to-tile mapping is defined in the Charmap.
|
||||||
|
// If CaseInsensitive is true, uppercase characters ('A'–'Z')
|
||||||
|
// are automatically converted to lowercase before lookup.
|
||||||
|
type TileFont struct {
|
||||||
|
Charmap map[rune]byte
|
||||||
|
|
||||||
|
// CaseInsensitive forces all characters to lowercase before lookup.
|
||||||
|
CaseInsensitive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTile returns the Tile corresponding to the given character.
|
||||||
|
//
|
||||||
|
// If CaseInsensitive is enabled, uppercase ASCII characters are converted
|
||||||
|
// to lowercase before lookup. If the character is not found in the Charmap,
|
||||||
|
// GetTile returns nil.
|
||||||
|
//
|
||||||
|
// The resulting Tile assumes a fixed tile size of 8x8 pixels
|
||||||
|
func (f TileFont) GetTile(char rune) *graphics.Tile {
|
||||||
|
// convert to lowercase
|
||||||
|
if f.CaseInsensitive && char >= 'A' && char <= 'Z' {
|
||||||
|
char = char + 0x20
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset, found := f.Charmap[char]; found {
|
||||||
|
return &graphics.Tile{
|
||||||
|
Size: 8,
|
||||||
|
X: offset & 0xF,
|
||||||
|
Y: offset >> 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
9
engine/graphics/texture.go
Normal file
9
engine/graphics/texture.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package graphics
|
||||||
|
|
||||||
|
import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
|
||||||
|
func LoadTextureFromMemory(fileType string, data []byte) rl.Texture2D {
|
||||||
|
img := rl.LoadImageFromMemory(fileType, data, int32(len(data)))
|
||||||
|
defer rl.UnloadImage(img)
|
||||||
|
return rl.LoadTextureFromImage(img)
|
||||||
|
}
|
||||||
18
engine/graphics/tile.go
Normal file
18
engine/graphics/tile.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package graphics
|
||||||
|
|
||||||
|
import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
|
||||||
|
type Tile struct {
|
||||||
|
Size byte
|
||||||
|
X, Y byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTexRect returns the texture rectangle.
|
||||||
|
func (t Tile) GetTexRect() rl.Rectangle {
|
||||||
|
return rl.Rectangle{
|
||||||
|
X: float32(t.X * t.Size),
|
||||||
|
Y: float32(t.Y * t.Size),
|
||||||
|
Width: float32(t.Size),
|
||||||
|
Height: float32(t.Size),
|
||||||
|
}
|
||||||
|
}
|
||||||
24
engine/render/context.go
Normal file
24
engine/render/context.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
gfxfont "tetris/engine/graphics/font"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
texture rl.Texture2D
|
||||||
|
font *gfxfont.TileFont = nil
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetTexture(tex rl.Texture2D) {
|
||||||
|
texture = tex
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTexture() rl.Texture2D {
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetFont(fnt *gfxfont.TileFont) {
|
||||||
|
font = fnt
|
||||||
|
}
|
||||||
26
engine/render/rect.go
Normal file
26
engine/render/rect.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DrawRectBorder draw a rectangle with a border around it.
|
||||||
|
// Note that the rectangle passed as the 'rect' parameter to the function represents the actual
|
||||||
|
// rectangle. The border will be drawn around it in all directions (outer border).
|
||||||
|
func DrawRectBorder(rect rl.RectangleInt32, col color.RGBA, border_size int32, border_col color.RGBA) {
|
||||||
|
rl.DrawRectangleRec(rl.Rectangle{
|
||||||
|
X: float32(rect.X),
|
||||||
|
Y: float32(rect.Y),
|
||||||
|
Width: float32(rect.Width),
|
||||||
|
Height: float32(rect.Height),
|
||||||
|
}, col)
|
||||||
|
|
||||||
|
rl.DrawRectangleLinesEx(rl.Rectangle{
|
||||||
|
X: float32(rect.X - border_size),
|
||||||
|
Y: float32(rect.Y - border_size),
|
||||||
|
Width: float32(rect.Width + (border_size * 2)),
|
||||||
|
Height: float32(rect.Height + (border_size * 2)),
|
||||||
|
}, float32(border_size), border_col)
|
||||||
|
}
|
||||||
107
engine/render/render.go
Normal file
107
engine/render/render.go
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"tetris/engine/system"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Title string
|
||||||
|
|
||||||
|
// Window
|
||||||
|
WindowWidth int32
|
||||||
|
WindowHeight int32
|
||||||
|
WindowFlags uint32
|
||||||
|
|
||||||
|
// Render target resolution
|
||||||
|
RenderHeight int32
|
||||||
|
RenderWidth int32
|
||||||
|
|
||||||
|
ScaleFlags ScaleFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
// target is the off-screen render target where all drawing operations are performed.
|
||||||
|
// It has a fixed resolution and is later scaled to the window size.
|
||||||
|
var target rl.RenderTexture2D
|
||||||
|
|
||||||
|
var scaleFlags ScaleFlags
|
||||||
|
|
||||||
|
// Init initializes the rendering system.
|
||||||
|
//
|
||||||
|
// It creates an off-screen render texture with the fixed resolution defined by config.RenderWidth/Height.
|
||||||
|
// This texture is where all tiles and game graphics are drawn before being scaled and presented.
|
||||||
|
func Init(config Config) {
|
||||||
|
// hyprland has a bug where the height of the window is 37 pixels taller than requested.
|
||||||
|
// so we just subtract it here.
|
||||||
|
if system.IsHyprland() {
|
||||||
|
config.WindowHeight = config.WindowHeight - 37
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleFlags = config.ScaleFlags
|
||||||
|
|
||||||
|
if config.WindowFlags > 0 {
|
||||||
|
rl.SetConfigFlags(config.WindowFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup window
|
||||||
|
rl.InitWindow(config.WindowWidth, config.WindowHeight, config.Title)
|
||||||
|
|
||||||
|
// Initialize render texture.
|
||||||
|
target = rl.LoadRenderTexture(config.RenderWidth, config.RenderHeight)
|
||||||
|
rl.SetTextureFilter(target.Texture, rl.TextureFilterNearest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit shuts down the rendering system.
|
||||||
|
//
|
||||||
|
// It unloads the render texture and frees any associated GPU resources.
|
||||||
|
// This should be called before the application exits.
|
||||||
|
func Exit() {
|
||||||
|
rl.UnloadRenderTexture(target)
|
||||||
|
rl.CloseWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin prepares the rendering system for a new frame.
|
||||||
|
//
|
||||||
|
// It binds the off-screen texture target and clears it to a black background.
|
||||||
|
// All tile drawing operations (e.g., DrawTile) should occur after Begin() and
|
||||||
|
// before End().
|
||||||
|
func Begin(col color.RGBA) {
|
||||||
|
// Bind texture so that all draw calls after are applied to target texture
|
||||||
|
rl.BeginTextureMode(target)
|
||||||
|
// Clear the texture
|
||||||
|
rl.ClearBackground(col)
|
||||||
|
}
|
||||||
|
|
||||||
|
// End finalizes the current frame and displays it on the screen.
|
||||||
|
//
|
||||||
|
// It ends the off-screen drawing session and stretches the texture target
|
||||||
|
// to fill the window. This function must be called after all drawing is done.
|
||||||
|
func End() {
|
||||||
|
// End drawing to the texture target.
|
||||||
|
rl.EndTextureMode()
|
||||||
|
|
||||||
|
// Begin drawing to screen buffer.
|
||||||
|
rl.BeginDrawing()
|
||||||
|
|
||||||
|
// Define source rectangle (flip vertically to match coordinate systems).
|
||||||
|
src := rl.Rectangle{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Width: float32(target.Texture.Width),
|
||||||
|
Height: -float32(target.Texture.Height),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the destination rectangle (window).
|
||||||
|
dest := scale(target.Texture.Width, target.Texture.Height,
|
||||||
|
int32(rl.GetRenderWidth()), int32(rl.GetRenderHeight()),
|
||||||
|
scaleFlags)
|
||||||
|
|
||||||
|
// Blit the off-screen texture to the screen's back buffer.
|
||||||
|
rl.DrawTexturePro(target.Texture, src, dest, rl.Vector2Zero(), 0.0, rl.White)
|
||||||
|
|
||||||
|
// Swap buffers
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
56
engine/render/scale.go
Normal file
56
engine/render/scale.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ScaleFlags byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Use integer scaling (pixel-perfect). Implies SCALE_NO_DOWNSCALE because integer < 1 becomes 0.
|
||||||
|
SCALE_INTEGER ScaleFlags = 1 << iota
|
||||||
|
|
||||||
|
// Do not allow shrinking below 1 (clamp scale >= 1).
|
||||||
|
SCALE_NO_DOWNSCALE
|
||||||
|
|
||||||
|
// Use "cover" (crop) instead of "contain" (letterbox). Default is contain.
|
||||||
|
SCALE_COVER
|
||||||
|
)
|
||||||
|
|
||||||
|
func scale(srcW, srcH, destW, destH int32, flags ScaleFlags) rl.Rectangle {
|
||||||
|
scale := float64(1)
|
||||||
|
sx := float64(destW) / float64(srcW)
|
||||||
|
sy := float64(destH) / float64(srcH)
|
||||||
|
|
||||||
|
// Contain (letterbox) uses min; Cover (crop) uses max.
|
||||||
|
if flags&SCALE_COVER != 0 {
|
||||||
|
scale = math.Max(sx, sy)
|
||||||
|
} else {
|
||||||
|
scale = math.Min(sx, sy)
|
||||||
|
}
|
||||||
|
|
||||||
|
if flags&SCALE_INTEGER != 0 {
|
||||||
|
// For contain, floor; for cover, ceil.
|
||||||
|
if flags&SCALE_COVER != 0 {
|
||||||
|
scale = math.Ceil(scale)
|
||||||
|
} else {
|
||||||
|
scale = math.Floor(scale)
|
||||||
|
}
|
||||||
|
// IntegerScale implies no fractional; clamp at 1 to avoid zero.
|
||||||
|
scale = max(1.0, scale)
|
||||||
|
} else if flags&SCALE_NO_DOWNSCALE != 0 && scale < 1.0 {
|
||||||
|
scale = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
w := float64(srcW) * scale
|
||||||
|
h := float64(srcH) * scale
|
||||||
|
|
||||||
|
return rl.Rectangle{
|
||||||
|
X: float32(math.Floor((float64(destW) - w) / 2.0)),
|
||||||
|
Y: float32(math.Floor((float64(destH) - h) / 2.0)),
|
||||||
|
Width: float32(w),
|
||||||
|
Height: float32(h),
|
||||||
|
}
|
||||||
|
}
|
||||||
31
engine/render/text.go
Normal file
31
engine/render/text.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DrawText(x, y, size int32, text string, col color.RGBA) {
|
||||||
|
destRect := rl.Rectangle{
|
||||||
|
X: float32(x),
|
||||||
|
Y: float32(y),
|
||||||
|
Width: float32(size),
|
||||||
|
Height: float32(size),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ch := range text {
|
||||||
|
if ch == ' ' {
|
||||||
|
destRect.X += float32(size)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tile := font.GetTile(ch)
|
||||||
|
if tile == nil {
|
||||||
|
destRect.X += float32(size)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rl.DrawTexturePro(texture, tile.GetTexRect(), destRect, rl.Vector2Zero(), 0, col)
|
||||||
|
destRect.X += float32(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
8
engine/render/texture.go
Normal file
8
engine/render/texture.go
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
|
||||||
|
// DrawTextureRec - Draw a rectangle from the current set texture.
|
||||||
|
func DrawTextureRec(src rl.Rectangle, dest rl.Rectangle) {
|
||||||
|
rl.DrawTexturePro(texture, src, dest, rl.Vector2Zero(), 0.0, rl.White)
|
||||||
|
}
|
||||||
23
engine/system/hypr.go
Normal file
23
engine/system/hypr.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsHyprland() bool {
|
||||||
|
// Primary signals
|
||||||
|
xdg := os.Getenv("XDG_RUNTIME_DIR")
|
||||||
|
his := os.Getenv("HYPRLAND_INSTANCE_SIGNATURE")
|
||||||
|
if xdg != "" && his != "" {
|
||||||
|
sock := filepath.Join(xdg, "hypr", his, ".socket.sock")
|
||||||
|
if st, err := os.Stat(sock); err == nil && !st.IsDir() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: desktop hint
|
||||||
|
hint := strings.ToLower(os.Getenv("XDG_CURRENT_DESKTOP"))
|
||||||
|
return strings.Contains(hint, "hypr")
|
||||||
|
}
|
||||||
47
game/draw/grid/grid.go
Normal file
47
game/draw/grid/grid.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package grid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"tetris/engine/render"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// How many pixels wide and tall each cell is.
|
||||||
|
CELL_SIZE = 32
|
||||||
|
|
||||||
|
// Number of pixels between each cell
|
||||||
|
CELL_SPACING = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func DrawBackground(rect rl.RectangleInt32, col color.RGBA, border_size int32, border_col color.RGBA) {
|
||||||
|
render.DrawRectBorder(rl.RectangleInt32{
|
||||||
|
X: int32(rect.X),
|
||||||
|
Y: int32(rect.Y),
|
||||||
|
Width: int32((rect.Width * (CELL_SIZE + CELL_SPACING)) + CELL_SPACING),
|
||||||
|
Height: int32((rect.Height * (CELL_SIZE + CELL_SPACING)) + CELL_SPACING),
|
||||||
|
}, col, border_size, border_col)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Draw(rect rl.RectangleInt32) {
|
||||||
|
// offset for background.
|
||||||
|
rect.X = rect.X + CELL_SPACING
|
||||||
|
rect.Y = rect.Y + CELL_SPACING
|
||||||
|
|
||||||
|
cell := rl.Rectangle{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Width: float32(CELL_SIZE),
|
||||||
|
Height: float32(CELL_SIZE),
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := range rect.Height {
|
||||||
|
for x := range rect.Width {
|
||||||
|
cell.X = float32(rect.X + (x * (CELL_SIZE + CELL_SPACING)))
|
||||||
|
cell.Y = float32(rect.Y + (y * (CELL_SIZE + CELL_SPACING)))
|
||||||
|
rl.DrawRectangleRec(cell, rl.Black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
game/draw/renderer.go
Normal file
40
game/draw/renderer.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package draw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"tetris/engine/render"
|
||||||
|
"tetris/game/draw/grid"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Border width when drawing frames
|
||||||
|
BORDER_WIDTH = 8
|
||||||
|
|
||||||
|
// Size for normal text
|
||||||
|
TEXT_SIZE = 32
|
||||||
|
|
||||||
|
// Text size for header texts
|
||||||
|
HEADER_TEXT_SIZE = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
type Renderer struct {
|
||||||
|
Theme *Theme
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Renderer) DrawText(x int32, y int32, text string) {
|
||||||
|
render.DrawText(x, y, TEXT_SIZE, text, r.Theme.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Renderer) DrawHeaderText(x int32, y int32, text string) {
|
||||||
|
render.DrawText(x, y, HEADER_TEXT_SIZE, text, r.Theme.TextHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Renderer) DrawFrame(rect rl.RectangleInt32) {
|
||||||
|
render.DrawRectBorder(rect, r.Theme.FrameBG, BORDER_WIDTH, r.Theme.FrameBorder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Renderer) DrawGrid(rect rl.RectangleInt32) {
|
||||||
|
grid.DrawBackground(rect, r.Theme.GridBackground, BORDER_WIDTH, r.Theme.FrameBorder)
|
||||||
|
grid.Draw(rect)
|
||||||
|
}
|
||||||
20
game/draw/theme.go
Normal file
20
game/draw/theme.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package draw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Theme holds the different colors used when rendering.
|
||||||
|
type Theme struct {
|
||||||
|
// Frame colors
|
||||||
|
FrameBG color.RGBA
|
||||||
|
FrameBorder color.RGBA
|
||||||
|
|
||||||
|
// Text colors
|
||||||
|
TextHeader color.RGBA
|
||||||
|
Text color.RGBA
|
||||||
|
|
||||||
|
// Grid Colors
|
||||||
|
GridBackground color.RGBA
|
||||||
|
GridEmptyCell color.RGBA
|
||||||
|
}
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
module tetris
|
||||||
|
|
||||||
|
go 1.24.6
|
||||||
|
|
||||||
|
require github.com/gen2brain/raylib-go/raylib v0.55.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/ebitengine/purego v0.7.1 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||||
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
|
)
|
||||||
8
go.sum
Normal file
8
go.sum
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
|
||||||
|
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||||
|
github.com/gen2brain/raylib-go/raylib v0.55.1 h1:1rdc10WvvYjtj7qijHnV9T38/WuvlT6IIL+PaZ6cNA8=
|
||||||
|
github.com/gen2brain/raylib-go/raylib v0.55.1/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
|
||||||
|
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||||
|
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||||
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
56
main.go
Normal file
56
main.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"tetris/assets"
|
||||||
|
"tetris/engine/graphics"
|
||||||
|
"tetris/engine/render"
|
||||||
|
"tetris/game/draw"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
render.Init(render.Config{
|
||||||
|
Title: "Tetris",
|
||||||
|
WindowWidth: 685,
|
||||||
|
WindowHeight: 600,
|
||||||
|
RenderWidth: 685,
|
||||||
|
RenderHeight: 600,
|
||||||
|
ScaleFlags: render.SCALE_INTEGER,
|
||||||
|
})
|
||||||
|
defer render.Exit()
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
texture := graphics.LoadTextureFromMemory(".png", assets.Sprite)
|
||||||
|
defer rl.UnloadTexture(texture)
|
||||||
|
render.SetTexture(texture)
|
||||||
|
render.SetFont(&assets.Font)
|
||||||
|
|
||||||
|
r := draw.Renderer{
|
||||||
|
Theme: &draw.Theme{
|
||||||
|
FrameBG: color.RGBA{R: 30, G: 30, B: 46, A: 255},
|
||||||
|
FrameBorder: color.RGBA{R: 242, G: 205, B: 205, A: 255},
|
||||||
|
TextHeader: color.RGBA{R: 242, G: 205, B: 205, A: 255},
|
||||||
|
Text: color.RGBA{R: 205, G: 214, B: 244, A: 255},
|
||||||
|
GridBackground: color.RGBA{R: 17, G: 17, B: 27, A: 255},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
render.Begin(r.Theme.GridBackground)
|
||||||
|
r.DrawGrid(rl.RectangleInt32{
|
||||||
|
X: 25,
|
||||||
|
Y: 25,
|
||||||
|
Width: 10,
|
||||||
|
Height: 16,
|
||||||
|
})
|
||||||
|
r.DrawFrame(rl.RectangleInt32{X: 400, Y: 25, Width: 250, Height: 100})
|
||||||
|
r.DrawHeaderText(410, 30, "Score")
|
||||||
|
r.DrawText(410, 65, "999999")
|
||||||
|
r.DrawFrame(rl.RectangleInt32{X: 400, Y: 150, Width: 250, Height: 200})
|
||||||
|
|
||||||
|
render.End()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue