Skip to content

Commit

Permalink
Merge pull request #119 from dusk125/v2
Browse files Browse the repository at this point in the history
Rebase 2.3.0 into v2
  • Loading branch information
dusk125 authored Aug 31, 2024
2 parents 9fd56cc + 5ce991f commit 1d79a74
Show file tree
Hide file tree
Showing 84 changed files with 5,622 additions and 44 deletions.
39 changes: 21 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Revived fork of the original [Pixel](https://github.com/faiface/pixel) library b


# Pixel 2
[![GoDoc](https://godoc.org/github.com/gopxl/pixel/v2?status.svg)](https://godoc.org/github.com/gopxl/pixel/v2)
[![Go Reference](https://pkg.go.dev/badge/github.com/gopxl/pixel/v2.svg)](https://pkg.go.dev/github.com/gopxl/pixel/v2)
[![Go build status](https://github.com/gopxl/pixel/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/gopxl/pixel/actions/workflows/go.yml?query=branch%3Amain)
[![Coverage Status](https://coveralls.io/repos/github/gopxl/pixel/badge.svg?branch=main)](https://coveralls.io/github/gopxl/pixel?branch=main)
[![Go Report Card](https://goreportcard.com/badge/github.com/gopxl/pixel/v2)](https://goreportcard.com/report/github.com/gopxl/pixel/v2)
[![Discord Chat](https://img.shields.io/discord/1158461233121468496)](https://discord.gg/q2DK4MP)
[![Discord Chat](https://img.shields.io/discord/1158461233121468496)](https://discord.gg/hPBTTXGDU3)

A hand-crafted 2D game library in Go. Take a look into the [features](#features) to see what it can
do.
Expand All @@ -31,17 +31,10 @@ See [requirements](#requirements) for the list of libraries necessary for compil

## Tutorial

The [Wiki of this repo](https://github.com/gopxl/pixel/wiki) contains an extensive tutorial
covering several topics of Pixel. Here's the content of the tutorial parts so far:
The [Wiki of this repo](./docs/README.md) contains an extensive tutorial
covering several topics of Pixel.

- [Creating a Window](https://github.com/gopxl/pixel/wiki/Creating-a-Window)
- [Drawing a Sprite](https://github.com/gopxl/pixel/wiki/Drawing-a-Sprite)
- [Moving, scaling and rotating with Matrix](https://github.com/gopxl/pixel/wiki/Moving,-scaling-and-rotating-with-Matrix)
- [Pressing keys and clicking mouse](https://github.com/gopxl/pixel/wiki/Pressing-keys-and-clicking-mouse)
- [Drawing efficiently with Batch](https://github.com/gopxl/pixel/wiki/Drawing-efficiently-with-Batch)
- [Drawing shapes with IMDraw](https://github.com/gopxl/pixel/wiki/Drawing-shapes-with-IMDraw)
- [Typing text on the screen](https://github.com/gopxl/pixel/wiki/Typing-text-on-the-screen)
- [Using a custom fragment shader](https://github.com/gopxl/pixel/wiki/Using-a-custom-fragment-shader)
For the tutorial walking through the basics of Pixel, check out [The Basics](./docs/Basics/Creating-a-Window.md)!

## [Examples](https://github.com/gopxl/pixel-examples)

Expand Down Expand Up @@ -80,9 +73,9 @@ Here's the list of the main features in Pixel. Although Pixel is still under hea
- Fast 2D graphics
- Sprites
- Primitive shapes with immediate mode style
[IMDraw](https://github.com/gopxl/pixel/wiki/Drawing-shapes-with-IMDraw) (circles, rectangles,
[IMDraw](./docs/Basics/Drawing-shapes-with-IMDraw.md) (circles, rectangles,
lines, ...)
- Optimized drawing with [Batch](https://github.com/gopxl/pixel/wiki/Drawing-efficiently-with-Batch)
- Optimized drawing with [Batch](./docs/Basics/Drawing-efficiently-with-Batch.md)
- Text drawing with [text](https://godoc.org/github.com/gopxl/pixel/v2/text) package
- Audio through a separate [Beep](https://github.com/gopxl/beep) library.
- Simple and convenient API
Expand All @@ -100,7 +93,7 @@ Here's the list of the main features in Pixel. Although Pixel is still under hea
multiplication and a few more features
- Pixel uses `float64` throughout the library, compatible with `"math"` package
- Geometry transformations with
[Matrix](https://github.com/gopxl/pixel/wiki/Moving,-scaling-and-rotating-with-Matrix)
[Matrix](./docs/Basics/Moving,-scaling-and-rotating-with-Matrix.md)
- Moving, scaling, rotating
- Easy camera implementation
- Off-screen drawing to Canvas or any other target (Batch, IMDraw, ...)
Expand Down Expand Up @@ -143,9 +136,7 @@ possible!

## Requirements

If you're using Windows and having trouble building Pixel, please check [this
guide](https://github.com/gopxl/pixel/wiki/Building-Pixel-on-Windows) on the
[wiki](https://github.com/gopxl/pixel/wiki).
If you're using Windows and having trouble building Pixel, please check [this guide](./docs/Compilation/Building-Pixel-on-Windows.md) on the [wiki](./docs/README.md).

OpenGL development libraries are needed for compilation. The dependencies
are same as for [GLFW](https://github.com/go-gl/glfw).
Expand All @@ -157,12 +148,24 @@ The OpenGL version used is **OpenGL 3.3**.
- On Ubuntu/Debian-like Linux distributions, you need `libgl1-mesa-dev` and `xorg-dev` packages.
- On CentOS/Fedora-like Linux distributions, you need `libX11-devel libXcursor-devel libXrandr-devel
libXinerama-devel mesa-libGL-devel libXi-devel libXxf86vm-devel` packages.
- On Linux to use Wayland instead of X11, compile your project with `-tags wayland`.
- See [here](http://www.glfw.org/docs/latest/compile.html#compile_deps) for full details.

**The combination of Go 1.8, macOS and latest XCode seems to be problematic** as mentioned in issue
[#7](https://github.com/gopxl/pixel/v2/issues/7). This issue is probably not related to Pixel.
**Upgrading to Go 1.8.1 fixes the issue.**

### Windows Subsystem for Linux

While pixel does run on Windows, you will likely have significantly better performance running in WSL2, which now has support for GUI applications built-in with WSLg.

Installation instructions [here](https://github.com/microsoft/wslg?tab=readme-ov-file#installing-wslg). If you already have an old version of WSL installed,
make sure to follow the upgrade instructions to get WSL2 as well as update your distribution of choice to version 2. Additionally, if you have an old `DISPLAY` environment variable set in your ~/.bashrc (or equivalent) for WSL1, you should remove it. This is now configured automatically.

Once WSL is setup, follow the usual Go and OpenGL installation instructions for your chosen distribution of linux.

Finally, add `export LIBGL_ALWAYS_INDIRECT=0` to your ~/.bashrc (or equivalent) if you see an error like `Error: creating window failed: VersionUnavailable: GLX: Failed to create context: GLXBadFBConfig` when attempting to launch an OpenGL application from WSL.

## Contributing

Join us in the [Discord Chat!](https://discord.gg/n2Y8uVneK6)
Expand Down
49 changes: 49 additions & 0 deletions backends/opengl/cursor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package opengl

import (
"image"
"runtime"

"github.com/go-gl/glfw/v3.3/glfw"
"github.com/gopxl/mainthread/v2"
"github.com/gopxl/pixel/v2"
)

type StandardCursor = glfw.StandardCursor

const (
ArrowCursor = glfw.ArrowCursor
IBeamCursor = glfw.IBeamCursor
CrosshairCursor = glfw.CrosshairCursor
HandCursor = glfw.HandCursor
HResizeCursor = glfw.HResizeCursor
VResizeCursor = glfw.VResizeCursor
)

type Cursor = glfw.Cursor

// CreateStandardCursor creates a new standard cursor.
func CreateStandardCursor(cursorId StandardCursor) *Cursor {
c := mainthread.CallVal(func() *Cursor {
return glfw.CreateStandardCursor(cursorId)
})
runtime.SetFinalizer(c, (*Cursor).Destroy)
return c
}

// CreateCursorImage creates a new cursor from an image with the specified hotspot (where the click is registered).
func CreateCursorImage(img image.Image, hot pixel.Vec) *Cursor {
c := mainthread.CallVal(func() *Cursor {
return glfw.CreateCursor(img, int(hot.X), int(hot.Y))
})
runtime.SetFinalizer(c, (*Cursor).Destroy)
return c
}

// SetCursor sets the cursor for the window.
func (w *Window) SetCursor(cursor *Cursor) {
mainthread.Call(func() {
w.window.SetCursor(cursor)
w.cursor = cursor
})
}
3 changes: 3 additions & 0 deletions backends/opengl/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ func (w *Window) initInput() {
})

w.window.SetCursorEnterCallback(func(_ *glfw.Window, entered bool) {
if entered && w.cursor != nil {
w.window.SetCursor(w.cursor)
}
w.input.MouseEnteredEvent(entered)
if w.mouseEnteredCallback != nil {
w.mouseEnteredCallback(w, entered)
Expand Down
22 changes: 21 additions & 1 deletion backends/opengl/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,12 @@ type WindowConfig struct {
// You can make the window visible later using Window.Show().
Invisible bool

//SamplesMSAA specifies the level of MSAA to be used. Must be one of 0, 2, 4, 8, 16. 0 to disable.
// SamplesMSAA specifies the level of MSAA to be used. Must be one of 0, 2, 4, 8, 16. 0 to disable.
SamplesMSAA int

// BoundsLimits specifies the minimum and maximum bounds of the resizable window.
// If the window is full screen or not resizable, this has no effect.
BoundsLimits pixel.Rect
}

// Window is a window handler. Use this type to manipulate a window (input, drawing, etc.).
Expand All @@ -105,6 +109,7 @@ type Window struct {
mouseEnteredCallback func(win *Window, entered bool)
mouseMovedCallback func(win *Window, pos pixel.Vec)
scrollCallback func(win *Window, scroll pixel.Vec)
cursor *Cursor
}

var currWin *Window
Expand Down Expand Up @@ -173,6 +178,10 @@ func NewWindow(cfg WindowConfig) (*Window, error) {
w.window.Show()
}

if !cfg.BoundsLimits.Empty() {
w.SetBoundsLimits(cfg.BoundsLimits)
}

// enter the OpenGL context
w.begin()
glhf.Init()
Expand All @@ -196,6 +205,9 @@ func NewWindow(cfg WindowConfig) (*Window, error) {
})
}

w.cursor = CreateStandardCursor(ArrowCursor)
w.SetCursor(w.cursor)

w.SetVSync(cfg.VSync)

w.initInput()
Expand Down Expand Up @@ -338,6 +350,14 @@ func (w *Window) Bounds() pixel.Rect {
return w.bounds
}

// SetBoundsLimits sets the minimum and maximum bounds of the window.
// If the window is full screen or not resizable, this function does nothing.
func (w *Window) SetBoundsLimits(limits pixel.Rect) {
mainthread.Call(func() {
w.window.SetSizeLimits(int(limits.Min.X), int(limits.Min.Y), int(limits.Max.X), int(limits.Max.Y))
})
}

func (w *Window) setFullscreen(monitor *Monitor) {
mainthread.Call(func() {
w.restore.xpos, w.restore.ypos = w.window.GetPos()
Expand Down
92 changes: 92 additions & 0 deletions data.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package pixel

import (
"embed"
"fmt"
"image"
"image/color"
"image/draw"
"io"
"math"
"os"
)

// zeroValueTriangleData is the default value of a TriangleData element
Expand Down Expand Up @@ -179,6 +182,95 @@ func verticalFlip(rgba *image.RGBA) {
}
}

type DecoderFunc func(io.Reader) (image.Image, error)

// DefaultDecoderFunc is a DecoderFunc that uses image.Decode to decode images.
// In order to decode, you must import the image formats you wish to use.
// ex. import _ "image/png"
func DefaultDecoderFunc(r io.Reader) (image.Image, error) {
i, _, err := image.Decode(r)
return i, err
}

// ImageFromEmbed loads an image from an embedded file using the given decoder.
//
// We take a decoder function (png.Decode, jpeg.Decode, etc.) as an argument; in order to decode images,
// you have to register the format (png, jpeg, etc.) with the image package, this will increase the number
// of dependencies imposed on a project. We want to avoid importing these in Pixel as it will increase the
// size of the project and it will increase maintanence if we miss a format, or if a new format is added.
//
// With this argument, you implicitly import and register the file formats you need and the Pixel project
// doesn't have to carry all formats around.
//
// The decoder can be nil, and Pixel will fallback onto using image.Decode and require you to import the
// formats you wish to use.
//
// See the example https://github.com/gopxl/pixel-examples/tree/main/core/loadingpictures.
func ImageFromEmbed(fs embed.FS, path string, decoder DecoderFunc) (image.Image, error) {
f, err := fs.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

if decoder == nil {
decoder = DefaultDecoderFunc
}

return decoder(f)
}

// ImageFromFile loads an image from a file using the given decoder.
//
// We take a decoder function (png.Decode, jpeg.Decode, etc.) as an argument; in order to decode images,
// you have to register the format (png, jpeg, etc.) with the image package, this will increase the number
// of dependencies imposed on a project. We want to avoid importing these in Pixel as it will increase the
// size of the project and it will increase maintanence if we miss a format, or if a new format is added.
//
// With this argument, you implicitly import and register the file formats you need and the Pixel project
// doesn't have to carry all formats around.
//
// The decoder can be nil, and Pixel will fallback onto using image.Decode and require you to import the
// formats you wish to use.
//
// See the example https://github.com/gopxl/pixel-examples/tree/main/core/loadingpictures.
func ImageFromFile(path string, decoder DecoderFunc) (image.Image, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

if decoder == nil {
decoder = DefaultDecoderFunc
}

return decoder(f)
}

// PictureDataFromFile loads an image from a file using the given decoder and converts it into PictureData.
//
// We take a decoder function (png.Decode, jpeg.Decode, etc.) as an argument; in order to decode images,
// you have to register the format (png, jpeg, etc.) with the image package, this will increase the number
// of dependencies imposed on a project. We want to avoid importing these in Pixel as it will increase the
// size of the project and it will increase maintanence if we miss a format, or if a new format is added.
//
// With this argument, you implicitly import and register the file formats you need and the Pixel project
// doesn't have to carry all formats around.
//
// The decoder can be nil, and Pixel will fallback onto using image.Decode and require you to import the
// formats you wish to use.
//
// See the example https://github.com/gopxl/pixel-examples/tree/main/core/loadingpictures.
func PictureDataFromFile(path string, decoder DecoderFunc) (*PictureData, error) {
img, err := ImageFromFile(path, decoder)
if err != nil {
return nil, err
}

return PictureDataFromImage(img), nil
}

// PictureDataFromImage converts an image.Image into PictureData.
//
// The resulting PictureData's Bounds will be the equivalent of the supplied image.Image's Bounds.
Expand Down
Loading

0 comments on commit 1d79a74

Please sign in to comment.