Basic wrapper around allegro5 libraries
- Depends on optional allegro libraries font, image, primitives and ttf as well.
This commit is contained in:
commit
2924980035
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.vscode
|
||||||
|
debug
|
||||||
|
debug.test
|
97
allegro5/bitmap.go
Normal file
97
allegro5/bitmap.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bitmap represents an in memory bitmap
|
||||||
|
type Bitmap struct {
|
||||||
|
bitmap *C.ALLEGRO_BITMAP
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
}
|
||||||
|
|
||||||
|
type DrawOptions struct {
|
||||||
|
Center bool
|
||||||
|
Scale *Scale
|
||||||
|
Tint *Color
|
||||||
|
}
|
||||||
|
|
||||||
|
type Scale struct {
|
||||||
|
Horizontal float32
|
||||||
|
Vertical float32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBitmap creates a new bitmap of given width and height
|
||||||
|
func NewBitmap(width, height int) (*Bitmap, error) {
|
||||||
|
b := C.al_create_bitmap(C.int(width), C.int(height))
|
||||||
|
if nil == b {
|
||||||
|
return nil, fmt.Errorf("Error creating bitmap")
|
||||||
|
}
|
||||||
|
return &Bitmap{b, width, height}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBitmap tries to load the image at the specified path as a bitmap
|
||||||
|
func LoadBitmap(path string) (*Bitmap, error) {
|
||||||
|
p := C.CString(path)
|
||||||
|
defer C.free(unsafe.Pointer(p))
|
||||||
|
b := C.al_load_bitmap(p)
|
||||||
|
if nil == b {
|
||||||
|
return nil, fmt.Errorf("Error loading bitmap")
|
||||||
|
}
|
||||||
|
width := int(C.al_get_bitmap_width(b))
|
||||||
|
height := int(C.al_get_bitmap_height(b))
|
||||||
|
return &Bitmap{b, width, height}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the bitmap at the given location
|
||||||
|
func (b *Bitmap) Draw(left, top float32) {
|
||||||
|
C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) DrawOptions(left, top float32, options DrawOptions) {
|
||||||
|
width := float32(b.width)
|
||||||
|
height := float32(b.height)
|
||||||
|
|
||||||
|
scale := nil != options.Scale
|
||||||
|
if scale {
|
||||||
|
width *= options.Scale.Horizontal
|
||||||
|
height *= options.Scale.Vertical
|
||||||
|
}
|
||||||
|
if options.Center {
|
||||||
|
left -= width * 0.5
|
||||||
|
top -= height * 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
if scale {
|
||||||
|
if nil == options.Tint {
|
||||||
|
C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
|
||||||
|
} else {
|
||||||
|
C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if nil == options.Tint {
|
||||||
|
C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0)
|
||||||
|
} else {
|
||||||
|
C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) Width() int {
|
||||||
|
return b.width
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) Height() int {
|
||||||
|
return b.height
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy destroys the bitmap
|
||||||
|
func (b *Bitmap) Destroy() {
|
||||||
|
C.al_destroy_bitmap(b.bitmap)
|
||||||
|
}
|
9
allegro5/c.go
Normal file
9
allegro5/c.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #cgo linux pkg-config: allegro-5 allegro_font-5 allegro_image-5 allegro_primitives-5 allegro_ttf-5
|
||||||
|
// #cgo windows LDFLAGS: -lallegro
|
||||||
|
// #cgo windows LDFLAGS: -lallegro_font
|
||||||
|
// #cgo windows LDFLAGS: -lallegro_image
|
||||||
|
// #cgo windows LDFLAGS: -lallegro_primitives
|
||||||
|
// #cgo windows LDFLAGS: -lallegro_ttf
|
||||||
|
import "C"
|
16
allegro5/color.go
Normal file
16
allegro5/color.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type Color struct {
|
||||||
|
color C.ALLEGRO_COLOR
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewColor(r, g, b byte) Color {
|
||||||
|
return Color{C.al_map_rgb(C.uchar(r), C.uchar(g), C.uchar(b))}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewColorAlpha(r, g, b, a byte) Color {
|
||||||
|
return Color{C.al_map_rgba(C.uchar(r), C.uchar(g), C.uchar(b), C.uchar(a))}
|
||||||
|
}
|
73
allegro5/display.go
Normal file
73
allegro5/display.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Display represents a display
|
||||||
|
type Display struct {
|
||||||
|
display *C.ALLEGRO_DISPLAY
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewDisplayOptions struct {
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Fullscreen bool
|
||||||
|
Resizable bool
|
||||||
|
Windowed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDisplay creates a display
|
||||||
|
func NewDisplay(options NewDisplayOptions) (*Display, error) {
|
||||||
|
var flags C.int = C.ALLEGRO_WINDOWED
|
||||||
|
if options.Fullscreen {
|
||||||
|
if options.Windowed {
|
||||||
|
flags |= C.ALLEGRO_FULLSCREEN_WINDOW
|
||||||
|
} else {
|
||||||
|
flags = C.ALLEGRO_FULLSCREEN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if options.Resizable {
|
||||||
|
flags |= C.ALLEGRO_RESIZABLE
|
||||||
|
}
|
||||||
|
C.al_set_new_display_flags(flags)
|
||||||
|
d := C.al_create_display(C.int(options.Width), C.int(options.Height))
|
||||||
|
if nil == d {
|
||||||
|
return nil, fmt.Errorf("Error creating display")
|
||||||
|
}
|
||||||
|
return &Display{d}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flips flips the buffer to the display
|
||||||
|
func (d *Display) Flip() {
|
||||||
|
C.al_flip_display()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Display) Width() int {
|
||||||
|
return int(C.al_get_display_width(d.display))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Display) Height() int {
|
||||||
|
return int(C.al_get_display_height(d.display))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Display) SetWindowTitle(title string) {
|
||||||
|
t := C.CString(title)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
C.al_set_window_title(d.display, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy destroys the display
|
||||||
|
func (d *Display) Destroy() {
|
||||||
|
C.al_destroy_display(d.display)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNewWindowTitle(title string) {
|
||||||
|
t := C.CString(title)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
C.al_set_new_window_title(t)
|
||||||
|
}
|
140
allegro5/event.go
Normal file
140
allegro5/event.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventQueue struct {
|
||||||
|
queue *C.ALLEGRO_EVENT_QUEUE
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event interface {
|
||||||
|
Stamp() float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventBase struct {
|
||||||
|
stamp float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eb EventBase) Stamp() float64 {
|
||||||
|
return eb.stamp
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplayCloseEvent struct {
|
||||||
|
EventBase
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyEvent struct {
|
||||||
|
EventBase
|
||||||
|
KeyCode int
|
||||||
|
Display *Display
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyCharEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
UnicodeCharacter rune
|
||||||
|
Modifiers uint
|
||||||
|
Repeat bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyDownEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyUpEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseButtonDownEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
Button uint
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseButtonUpEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
Button uint
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseEvent struct {
|
||||||
|
EventBase
|
||||||
|
X, Y int
|
||||||
|
Z, W int
|
||||||
|
Display *Display
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseMoveEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
DeltaX, DeltaY int
|
||||||
|
DeltaZ, DeltaW int
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEventQueue() (*EventQueue, error) {
|
||||||
|
q := C.al_create_event_queue()
|
||||||
|
if nil == q {
|
||||||
|
return nil, fmt.Errorf("Unable to create event queue")
|
||||||
|
}
|
||||||
|
return &EventQueue{q}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) register(source *C.ALLEGRO_EVENT_SOURCE) {
|
||||||
|
C.al_register_event_source(eq.queue, source)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterDisplay(d *Display) {
|
||||||
|
eq.register(C.al_get_display_event_source(d.display))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterMouse() {
|
||||||
|
eq.register(C.al_get_mouse_event_source())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterKeyboard() {
|
||||||
|
eq.register(C.al_get_keyboard_event_source())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event {
|
||||||
|
any := (*C.ALLEGRO_ANY_EVENT)(unsafe.Pointer(e))
|
||||||
|
eb := EventBase{float64(any.timestamp)}
|
||||||
|
switch any._type {
|
||||||
|
case C.ALLEGRO_EVENT_DISPLAY_CLOSE:
|
||||||
|
return &DisplayCloseEvent{EventBase{float64(any.timestamp)}}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_AXES:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseMoveEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, int(mouse.dx), int(mouse.dy), int(mouse.dz), int(mouse.dw), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseButtonDownEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, uint(mouse.button), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseButtonUpEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, uint(mouse.button), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_DOWN:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyDownEvent{KeyEvent{eb, int(key.keycode), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_UP:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyUpEvent{KeyEvent{eb, int(key.keycode), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_CHAR:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyCharEvent{KeyEvent{eb, int(key.keycode), nil}, rune(key.unichar), uint(key.modifiers), bool(key.repeat)}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) Get() Event {
|
||||||
|
var event C.ALLEGRO_EVENT
|
||||||
|
if !bool(C.al_get_next_event(eq.queue, &event)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return eq.mapEvent(&event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) Destroy() {
|
||||||
|
C.al_destroy_event_queue(eq.queue)
|
||||||
|
}
|
58
allegro5/font.go
Normal file
58
allegro5/font.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_font.h>
|
||||||
|
// #include <allegro5/allegro_ttf.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Font struct {
|
||||||
|
font *C.ALLEGRO_FONT
|
||||||
|
}
|
||||||
|
|
||||||
|
type HorizontalAlignment int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AlignLeft HorizontalAlignment = iota
|
||||||
|
AlignCenter
|
||||||
|
AlignRight
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadTTFFont(path string, size int) (*Font, error) {
|
||||||
|
p := C.CString(path)
|
||||||
|
defer C.free(unsafe.Pointer(p))
|
||||||
|
|
||||||
|
f := C.al_load_ttf_font(p, C.int(size), 0)
|
||||||
|
if nil == f {
|
||||||
|
return nil, fmt.Errorf("Unable to load TTF font '%s'", path)
|
||||||
|
}
|
||||||
|
return &Font{f}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) drawFlags(a HorizontalAlignment) C.int {
|
||||||
|
switch a {
|
||||||
|
case AlignLeft:
|
||||||
|
return C.ALLEGRO_ALIGN_LEFT
|
||||||
|
case AlignCenter:
|
||||||
|
return C.ALLEGRO_ALIGN_CENTRE
|
||||||
|
case AlignRight:
|
||||||
|
return C.ALLEGRO_ALIGN_RIGHT
|
||||||
|
}
|
||||||
|
return C.ALLEGRO_ALIGN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) Draw(left, top float32, color Color, align HorizontalAlignment, text string) {
|
||||||
|
t := C.CString(text)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
|
||||||
|
flags := f.drawFlags(align)
|
||||||
|
C.al_draw_text(f.font, color.color, C.float(left), C.float(top), flags, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) Destroy() {
|
||||||
|
C.al_destroy_font(f.font)
|
||||||
|
}
|
26
allegro5/graphics.go
Normal file
26
allegro5/graphics.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// BitmapFlag is extra information provided for creating a bitmap
|
||||||
|
type BitmapFlag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BitmapFlagLinearScaleDown enables linear scaling when scaling down. Gives better results when combined with BitmapFlagMipMap
|
||||||
|
BitmapFlagLinearScaleDown BitmapFlag = C.ALLEGRO_MIN_LINEAR
|
||||||
|
// BitmapFlagLinearScaleUp enables linear scaling when scaling up.
|
||||||
|
BitmapFlagLinearScaleUp = C.ALLEGRO_MAG_LINEAR
|
||||||
|
// BitmapFlagMipMap enables mipmaps for drawing a scaled down version. Bitmap must square and its sides must be a power of two.
|
||||||
|
BitmapFlagMipMap = C.ALLEGRO_MIPMAP
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClearToColor clears the target bitmap to the color
|
||||||
|
func ClearToColor(c Color) {
|
||||||
|
C.al_clear_to_color(c.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNewBitmapFlags sets the default bitmap flags for a newly created bitmap
|
||||||
|
func SetNewBitmapFlags(flags BitmapFlag) {
|
||||||
|
C.al_set_new_bitmap_flags(C.int(flags))
|
||||||
|
}
|
9
allegro5/primitives.go
Normal file
9
allegro5/primitives.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_primitives.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func DrawLine(x1, y1, x2, y2 float32, c Color, thickness float32) {
|
||||||
|
C.al_draw_line(C.float(x1), C.float(y1), C.float(x2), C.float(y2), c.color, C.float(thickness))
|
||||||
|
}
|
49
allegro5/system.go
Normal file
49
allegro5/system.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package allegro5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_font.h>
|
||||||
|
// #include <allegro5/allegro_image.h>
|
||||||
|
// #include <allegro5/allegro_primitives.h>
|
||||||
|
// #include <allegro5/allegro_ttf.h>
|
||||||
|
// bool init() {
|
||||||
|
// return al_init();
|
||||||
|
// }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InitConfig struct {
|
||||||
|
Font bool
|
||||||
|
Image bool
|
||||||
|
Primitives bool
|
||||||
|
Keyboard bool
|
||||||
|
Mouse bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the Allegro system
|
||||||
|
func Init(config InitConfig) error {
|
||||||
|
if !bool(C.init()) {
|
||||||
|
return fmt.Errorf("Failed to initialize Allegro")
|
||||||
|
}
|
||||||
|
if config.Font && !bool(C.al_init_font_addon()) {
|
||||||
|
return fmt.Errorf("Failed to initialize font addon")
|
||||||
|
}
|
||||||
|
if config.Font && !bool(C.al_init_ttf_addon()) {
|
||||||
|
return fmt.Errorf("Failed to initialize ttf addon")
|
||||||
|
}
|
||||||
|
if config.Image && !bool(C.al_init_image_addon()) {
|
||||||
|
return fmt.Errorf("Failed to initialize image addon")
|
||||||
|
}
|
||||||
|
if config.Primitives && !bool(C.al_init_primitives_addon()) {
|
||||||
|
return fmt.Errorf("Failed to initialize primitives addon")
|
||||||
|
}
|
||||||
|
if config.Keyboard && !bool(C.al_install_keyboard()) {
|
||||||
|
return fmt.Errorf("Failed to install keyboard")
|
||||||
|
}
|
||||||
|
if config.Mouse && !bool(C.al_install_mouse()) {
|
||||||
|
return fmt.Errorf("Failed to install mouse")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user