move sdl module to github.com/vlang/sdl

pull/4177/head
Alexander Medvednikov 2020-04-01 15:27:28 +02:00
parent 7fd81d3abb
commit 3dae1cc131
21 changed files with 3 additions and 1808 deletions

View File

@ -1 +0,0 @@
main

View File

@ -1,31 +0,0 @@
module main
import sdl
fn main() {
C.SDL_Init(C.SDL_INIT_VIDEO)
window := C.SDL_CreateWindow('Hello SDL2', 300, 300, 500, 300, 0)
renderer := C.SDL_CreateRenderer(window, -1, C.SDL_RENDERER_ACCELERATED | C.SDL_RENDERER_PRESENTVSYNC)
mut should_close := false
for {
evt := SDL_Event{}
for 0 < sdl.poll_event(&evt) {
match int(evt.@type) {
C.SDL_QUIT { should_close = true }
else {}
}
}
if should_close {
break
}
C.SDL_SetRenderDrawColor(renderer, 255, 55, 55, 255)
C.SDL_RenderClear(renderer)
C.SDL_RenderPresent(renderer)
}
C.SDL_DestroyRenderer(renderer)
C.SDL_DestroyWindow(window)
C.SDL_Quit()
}

View File

@ -1 +0,0 @@
tvintris

View File

@ -1,17 +0,0 @@
# tVintris
tvintris.v is a dual-player (local) version based on original source from <a href='https://github.com/vlang/v/examples/tetris'>tetris example</a> by Alex M.
It is largely inspired by ancient game Twintris.
-uses vlib sdl module
![tVintris screenshot](images/tvintris.png)
# how to run tVintris
`$ v run .`
# Credits
Colors, Music and Sounds inspired/ripped from amiga title Twintris (1990 nostalgia !)
- Graphician : Svein Berge
- Musician : Tor Bernhard Gausen (Walkman/Cryptoburners)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 B

View File

@ -1,854 +0,0 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
// SDL2 port+wrapper, Twintris-like dual-game logic,
// and more, by Nicolas Sauzede 2019.
module main
import rand
import time
import os
import math
import sdl
import sdl.image as img
import sdl.mixer as mix
import sdl.ttf as ttf
[inline] fn sdl_fill_rect(s &SDL_Surface,r &SDL_Rect,c &SDL_Color){sdl.fill_rect(s,r,c)}
const (
Title = 'tVintris'
BASE = os.dir( os.real_path( os.executable() ) )
FontName = BASE + '/../../assets/fonts/RobotoMono-Regular.ttf'
MusicName = BASE + '/sounds/TwintrisThosenine.mod'
SndBlockName = BASE + '/sounds/block.wav'
SndLineName = BASE + '/sounds/single.wav'
SndDoubleName = BASE + '/sounds/triple.wav'
VLogo = BASE + '/images/v-logo_30_30.png'
BlockSize = 20 // pixels
FieldHeight = 20 // # of blocks
FieldWidth = 10
TetroSize = 4
WinWidth = BlockSize * FieldWidth * 3
WinHeight = BlockSize * FieldHeight
TimerPeriod = 250 // ms
TextSize = 16
AudioBufSize = 1024
P2FIRE = C.SDLK_l
P2UP = C.SDLK_UP
P2DOWN = C.SDLK_DOWN
P2LEFT = C.SDLK_LEFT
P2RIGHT = C.SDLK_RIGHT
P1FIRE = C.SDLK_s
P1UP = C.SDLK_w
P1DOWN = C.SDLK_x
P1LEFT = C.SDLK_a
P1RIGHT = C.SDLK_d
NJOYMAX = 2
// joystick name => enter your own device name
JOYP1NAME = 'Generic X-Box pad'
// following are joystick button number
JBP1FIRE = 1
// following are joystick hat value
JHP1UP = 1
JHP1DOWN = 4
JHP1LEFT = 8
JHP1RIGHT = 3
// joystick name => enter your own device name
JOYP2NAME = 'RedOctane Guitar Hero X-plorer'
// following are joystick button number
JBP2FIRE = 0
// following are joystick hat value
JHP2UP = 4
JHP2DOWN = 1
JHP2LEFT = 8
JHP2RIGHT = 2
)
const (
mix_version = mix.version
ttf_version = ttf.version
)
const (
// Tetros' 4 possible states are encoded in binaries
BTetros = [
// 0000 0
// 0000 0
// 0110 6
// 0110 6
[66, 66, 66, 66],
// 0000 0
// 0000 0
// 0010 2
// 0111 7
[27, 131, 72, 232],
// 0000 0
// 0000 0
// 0011 3
// 0110 6
[36, 231, 36, 231],
// 0000 0
// 0000 0
// 0110 6
// 0011 3
[63, 132, 63, 132],
// 0000 0
// 0011 3
// 0001 1
// 0001 1
[311, 17, 223, 74],
// 0000 0
// 0011 3
// 0010 2
// 0010 2
[322, 71, 113, 47],
// Special case since 15 can't be used
// 1111
[1111, 9, 1111, 9],
]
// Each tetro has its unique color
Colors = [
SDL_Color{byte(0), byte(0), byte(0), byte(0)}, // unused ?
SDL_Color{byte(0), byte(0x62), byte(0xc0), byte(0)}, // quad : darkblue 0062c0
SDL_Color{byte(0xca), byte(0x7d), byte(0x5f), byte(0)}, // tricorn : lightbrown ca7d5f
SDL_Color{byte(0), byte(0xc1), byte(0xbf), byte(0)}, // short topright : lightblue 00c1bf
SDL_Color{byte(0), byte(0xc1), byte(0), byte(0)}, // short topleft : lightgreen 00c100
SDL_Color{byte(0xbf), byte(0xbe), byte(0), byte(0)}, // long topleft : yellowish bfbe00
SDL_Color{byte(0xd1), byte(0), byte(0xbf), byte(0)}, // long topright : pink d100bf
SDL_Color{byte(0xd1), byte(0), byte(0), byte(0)}, // longest : lightred d10000
SDL_Color{byte(0), byte(170), byte(170), byte(0)}, // unused ?
]
// Background color
BackgroundColor = SDL_Color{byte(0), byte(0), byte(0), byte(0)}
// Foreground color
ForegroundColor = SDL_Color{byte(0), byte(170), byte(170), byte(0)}
// Text color
TextColor = SDL_Color{byte(0xca), byte(0x7d), byte(0x5f), byte(0)}
)
// TODO: type Tetro [TetroSize]struct{ x, y int }
struct Block {
mut:
x int
y int
}
enum GameState {
paused running gameover
}
struct AudioContext {
mut:
music voidptr
volume int
waves [3]voidptr
}
struct SdlContext {
pub mut:
// VIDEO
w int
h int
window voidptr
renderer voidptr
screen &SDL_Surface
texture voidptr
// AUDIO
actx AudioContext
// JOYSTICKS
jnames [2]string
jids [2]int
// V logo
v_logo &SDL_Surface
tv_logo voidptr
}
struct Game {
mut:
// Score of the current game
score int
// Count consecutive lines for scoring
lines int
// State of the current game
state GameState
// X offset of the game display
ofs_x int
// keys
k_fire int
k_up int
k_down int
k_left int
k_right int
// joystick ID
joy_id int
// joystick buttons
jb_fire int
// joystick hat values
jh_up int
jh_down int
jh_left int
jh_right int
// game rand seed
seed int
seed_ini int
// Position of the current tetro
pos_x int
pos_y int
// field[y][x] contains the color of the block with (x,y) coordinates
// "-1" border is to avoid bounds checking.
// -1 -1 -1 -1
// -1 0 0 -1
// -1 0 0 -1
// -1 -1 -1 -1
field [][]int
// TODO: tetro Tetro
tetro []Block
// TODO: tetros_cache []Tetro
tetros_cache []Block
// Index of the current tetro. Refers to its color.
tetro_idx int
// Index of the next tetro. Refers to its color.
tetro_next int
// tetro stats : buckets of drawn tetros
tetro_stats []int
// total number of drawn tetros
tetro_total int
// Index of the rotation (0-3)
rotation_idx int
// SDL2 context for drawing
sdl SdlContext
// TTF context for font drawing
font voidptr
}
fn (sdlc mut SdlContext) set_sdl_context(w int, h int, title string) {
C.SDL_Init(C.SDL_INIT_VIDEO | C.SDL_INIT_AUDIO | C.SDL_INIT_JOYSTICK)
C.atexit(C.SDL_Quit)
C.TTF_Init()
C.atexit(C.TTF_Quit)
bpp := 32
sdl.create_window_and_renderer(w, h, 0, &sdlc.window, &sdlc.renderer)
// C.SDL_CreateWindowAndRenderer(w, h, 0, voidptr(&sdlc.window), voidptr(&sdlc.renderer))
C.SDL_SetWindowTitle(sdlc.window, title.str)
sdlc.w = w
sdlc.h = h
sdlc.screen = sdl.create_rgb_surface(0, w, h, bpp, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000)
sdlc.texture = C.SDL_CreateTexture(sdlc.renderer, C.SDL_PIXELFORMAT_ARGB8888, C.SDL_TEXTUREACCESS_STREAMING, w, h)
C.Mix_Init(C.MIX_INIT_MOD)
C.atexit(C.Mix_Quit)
if C.Mix_OpenAudio(48000,C.MIX_DEFAULT_FORMAT,2,AudioBufSize) < 0 {
println('couldn\'t open audio')
}
println('opening music $MusicName')
sdlc.actx.music = C.Mix_LoadMUS(MusicName.str)
sdlc.actx.waves[0] = C.Mix_LoadWAV(SndBlockName.str)
sdlc.actx.waves[1] = C.Mix_LoadWAV(SndLineName.str)
sdlc.actx.waves[2] = C.Mix_LoadWAV(SndDoubleName.str)
sdlc.actx.volume = C.SDL_MIX_MAXVOLUME
if C.Mix_PlayMusic(sdlc.actx.music, 1) != -1 {
C.Mix_VolumeMusic(sdlc.actx.volume)
}
njoy := C.SDL_NumJoysticks()
for i in 0..njoy {
C.SDL_JoystickOpen(i)
jn := tos_clone(sdl.joystick_name_for_index(i))
println('JOY NAME $jn')
for j in 0..NJOYMAX {
if sdlc.jnames[j] == jn {
println('FOUND JOYSTICK $j $jn ID=$i')
sdlc.jids[j] = i
}
}
}
flags := C.IMG_INIT_PNG
imgres := img.img_init(flags)
if (imgres & flags) != flags {
println('error initializing image library.')
}
println('opening logo $VLogo')
sdlc.v_logo = img.load(VLogo)
if !isnil(sdlc.v_logo) {
// println('got v_logo=$sdlc.v_logo')
sdlc.tv_logo = sdl.create_texture_from_surface(sdlc.renderer, sdlc.v_logo)
// println('got tv_logo=$sdlc.tv_logo')
}
C.SDL_JoystickEventState(C.SDL_ENABLE)
}
fn main() {
println('tVintris -- tribute to venerable Twintris')
mut game := &Game{ font: 0 }
game.sdl.jnames[0] = JOYP1NAME
game.sdl.jnames[1] = JOYP2NAME
game.sdl.jids[0] = -1
game.sdl.jids[1] = -1
game.sdl.set_sdl_context(WinWidth, WinHeight, Title)
game.font = C.TTF_OpenFont(FontName.str, TextSize)
seed := time.now().unix
mut game2 := &Game{ font: 0 }
game2.sdl = game.sdl
game2.font = game.font
game.joy_id = game.sdl.jids[0]
// println('JOY1 id=${game.joy_id}')
game2.joy_id = game.sdl.jids[1]
// println('JOY2 id=${game2.joy_id}')
// delay uses milliseconds so 1000 ms / 30 frames (30fps) roughly = 33.3333 ms/frame
time_per_frame := 1000.0 / 30.0
game.k_fire = P1FIRE
game.k_up = P1UP
game.k_down = P1DOWN
game.k_left = P1LEFT
game.k_right = P1RIGHT
game.jb_fire = JBP1FIRE
game.jh_up = JHP1UP
game.jh_down = JHP1DOWN
game.jh_left = JHP1LEFT
game.jh_right = JHP1RIGHT
game.ofs_x = 0
game.seed_ini = seed
game.init_game()
game.state = .running
go game.run() // Run the game loop in a new thread
game2.k_fire = P2FIRE
game2.k_up = P2UP
game2.k_down = P2DOWN
game2.k_left = P2LEFT
game2.k_right = P2RIGHT
game2.jb_fire = JBP2FIRE
game2.jh_up = JHP2UP
game2.jh_down = JHP2DOWN
game2.jh_left = JHP2LEFT
game2.jh_right = JHP2RIGHT
game2.ofs_x = WinWidth * 2 / 3
game2.seed_ini = seed
game2.init_game()
game2.state = .running
go game2.run() // Run the game loop in a new thread
mut g := Game{ font: 0 }
mut should_close := false
mut total_frame_ticks := u64(0)
mut total_frames := u32(0)
for {
total_frames++
start_ticks := sdl.get_perf_counter()
g1 := game
g2 := game2
// here we determine which game contains most recent state
if g1.tetro_total > g.tetro_total {
g = *g1
}
if g2.tetro_total > g.tetro_total {
g = *g2
}
g.draw_begin()
g1.draw_tetro()
g1.draw_field()
g2.draw_tetro()
g2.draw_field()
g.draw_middle()
g1.draw_score()
g2.draw_score()
g.draw_stats()
g.draw_v_logo()
g.draw_end()
// game.handle_events() // CRASHES if done in function ???
evt := SDL_Event{}
for 0 < sdl.poll_event(&evt) {
match int(evt.@type) {
C.SDL_QUIT { should_close = true }
C.SDL_KEYDOWN {
key := evt.key.keysym.sym
if key == C.SDLK_ESCAPE {
should_close = true
break
}
game.handle_key(key)
game2.handle_key(key)
}
C.SDL_JOYBUTTONDOWN {
jb := int(evt.jbutton.button)
joyid := evt.jbutton.which
// println('JOY BUTTON $jb $joyid')
game.handle_jbutton(jb, joyid)
game2.handle_jbutton(jb, joyid)
}
C.SDL_JOYHATMOTION {
jh := int(evt.jhat.hat)
jv := int(evt.jhat.value)
joyid := evt.jhat.which
// println('JOY HAT $jh $jv $joyid')
game.handle_jhat(jh, jv, joyid)
game2.handle_jhat(jh, jv, joyid)
}
else {}
}
}
if should_close {
break
}
end_ticks := sdl.get_perf_counter()
total_frame_ticks += end_ticks-start_ticks
elapsed_time := f64(end_ticks - start_ticks) / f64(sdl.get_perf_frequency())
// current_fps := 1.0 / elapsed_time
// should limit system to (1 / time_per_frame) fps
sdl.delay(u32(math.floor(time_per_frame - elapsed_time)))
}
if game.font != voidptr(0) {
C.TTF_CloseFont(game.font)
}
if game.sdl.actx.music != voidptr(0) {
C.Mix_FreeMusic(game.sdl.actx.music)
}
C.Mix_CloseAudio()
if game.sdl.actx.waves[0] != voidptr(0) {
C.Mix_FreeChunk(game.sdl.actx.waves[0])
}
if game.sdl.actx.waves[1] != voidptr(0) {
C.Mix_FreeChunk(game.sdl.actx.waves[1])
}
if game.sdl.actx.waves[2] != voidptr(0) {
C.Mix_FreeChunk(game.sdl.actx.waves[2])
}
if !isnil(game.sdl.tv_logo) {
sdl.destroy_texture(game.sdl.tv_logo)
}
if !isnil(game.sdl.v_logo) {
sdl.free_surface(game.sdl.v_logo)
}
}
enum Action {
idle space fire
}
fn (game mut Game) handle_key(key int) {
// global keys
mut action := Action.idle
match key {
C.SDLK_SPACE { action = .space }
game.k_fire { action = .fire }
else {}
}
if action == .space {
match game.state {
.running {
C.Mix_PauseMusic()
game.state = .paused
}
.paused {
C.Mix_ResumeMusic()
game.state = .running
}
else {}
}
}
if action == .fire {
match game.state {
.gameover {
game.init_game()
game.state = .running
}
else {}
}
}
if game.state != .running { return }
// keys while game is running
match key {
game.k_up { game.rotate_tetro() }
game.k_left { game.move_right(-1) }
game.k_right { game.move_right(1) }
game.k_down { game.move_tetro() } // drop faster when the player presses <down>
else {}
}
}
fn (game mut Game) handle_jbutton(jb int, joyid int) {
if joyid != game.joy_id {
return
}
// global buttons
mut action := Action.idle
match jb {
game.jb_fire { action = .fire }
else {}
}
if action == .fire {
match game.state {
.gameover {
game.init_game()
game.state = .running
}
else {}
}
}
}
fn (game mut Game) handle_jhat(jh int, jv int, joyid int) {
if joyid != game.joy_id {
return
}
if game.state != .running { return }
// println('testing hat values.. joyid=$joyid jh=$jh jv=$jv')
// hat values while game is running
match jv {
game.jh_up { game.rotate_tetro() }
game.jh_left { game.move_right(-1) }
game.jh_right { game.move_right(1) }
game.jh_down { game.move_tetro() } // drop faster when the player presses <down>
else {}
}
}
fn (g mut Game) init_game() {
g.score = 0
g.tetro_total = 0
g.tetro_stats = [0, 0, 0, 0, 0, 0, 0]
g.parse_tetros()
g.seed = g.seed_ini
g.generate_tetro()
g.field = []
// Generate the field, fill it with 0's, add -1's on each edge
for i in 0..FieldHeight + 2 {
mut row := [0].repeat(FieldWidth + 2)
row[0] = - 1
row[FieldWidth + 1] = - 1
g.field << row
}
mut first_row := g.field[0]
mut last_row := g.field[FieldHeight + 1]
for j in 0..FieldWidth + 2 {
first_row[j] = - 1
last_row[j] = - 1
}
}
fn (g mut Game) parse_tetros() {
for b_tetros in BTetros {
for b_tetro in b_tetros {
for t in parse_binary_tetro(b_tetro) {
g.tetros_cache << t
}
}
}
}
fn (g mut Game) run() {
for {
if g.state == .running {
g.move_tetro()
n := g.delete_completed_lines()
if n > 0 {
g.lines += n
} else {
if g.lines > 0 {
if g.lines > 1 {
C.Mix_PlayChannel(0, g.sdl.actx.waves[2], 0)
} else if g.lines == 1 {
C.Mix_PlayChannel(0, g.sdl.actx.waves[1], 0)
}
g.score += 10 * g.lines * g.lines
g.lines = 0
}
}
}
time.sleep_ms(TimerPeriod) // medium delay between game step
}
}
fn (game mut Game) rotate_tetro() {
// Rotate the tetro
old_rotation_idx := game.rotation_idx
game.rotation_idx++
if game.rotation_idx == TetroSize {
game.rotation_idx = 0
}
game.get_tetro()
if !game.move_right(0) {
game.rotation_idx = old_rotation_idx
game.get_tetro()
}
if game.pos_x < 0 {
game.pos_x = 1
}
}
fn (g mut Game) move_tetro() {
// Check each block in current tetro
for block in g.tetro {
y := block.y + g.pos_y + 1
x := block.x + g.pos_x
// Reached the bottom of the screen or another block?
// TODO: if g.field[y][x] != 0
//if g.field[y][x] != 0 {
row := g.field[y]
if row[x] != 0 {
// The new tetro has no space to drop => end of the game
if g.pos_y < 2 {
g.state = .gameover
g.tetro_total = 0
return
}
// Drop it and generate a new one
g.drop_tetro()
g.generate_tetro()
C.Mix_PlayChannel(0, g.sdl.actx.waves[0], 0)
return
}
}
g.pos_y++
}
fn (g mut Game) move_right(dx int) bool {
// Reached left/right edge or another tetro?
for i in 0..TetroSize {
tetro := g.tetro[i]
y := tetro.y + g.pos_y
x := tetro.x + g.pos_x + dx
row := g.field[y]
if row[x] != 0 {
// Do not move
return false
}
}
g.pos_x += dx
return true
}
fn (g &Game) delete_completed_lines() int {
mut n := 0
for y := FieldHeight; y >= 1; y-- {
n += g.delete_completed_line(y)
}
return n
}
fn (g &Game) delete_completed_line(y int) int {
for x := 1; x <= FieldWidth; x++ {
f := g.field[y]
if f[x] == 0 {
return 0
}
}
// Move everything down by 1 position
for yy := y - 1; yy >= 1; yy-- {
for x := 1; x <= FieldWidth; x++ {
mut a := g.field[yy + 1]
b := g.field[yy]
a[x] = b[x]
}
}
return 1
}
// Draw a rand tetro index
fn (g mut Game) rand_tetro() int {
cur := g.tetro_next
g.tetro_next = rand.rand_r(&g.seed)
g.tetro_next = g.tetro_next % BTetros.len
return cur
}
// Place a new tetro on top
fn (g mut Game) generate_tetro() {
g.pos_y = 0
g.pos_x = FieldWidth / 2 - TetroSize / 2
g.tetro_idx = g.rand_tetro()
// println('idx=${g.tetro_idx}')
g.tetro_stats[g.tetro_idx]+= 2 -1
g.tetro_total++
g.rotation_idx = 0
g.get_tetro()
}
// Get the right tetro from cache
fn (g mut Game) get_tetro() {
idx := g.tetro_idx * TetroSize * TetroSize + g.rotation_idx * TetroSize
g.tetro = g.tetros_cache[idx .. idx + TetroSize]
}
fn (g &Game) drop_tetro() {
for i in 0..TetroSize {
tetro := g.tetro[i]
x := tetro.x + g.pos_x
y := tetro.y + g.pos_y
// Remember the color of each block
// TODO: g.field[y][x] = g.tetro_idx + 1
mut row := g.field[y]
row[x] = g.tetro_idx + 1
}
}
fn (g &Game) draw_tetro() {
for i in 0..TetroSize {
tetro := g.tetro[i]
g.draw_block(g.pos_y + tetro.y, g.pos_x + tetro.x, g.tetro_idx + 1)
}
}
fn (g &Game) draw_block(i, j, color_idx int) {
rect := SDL_Rect {g.ofs_x + (j - 1) * BlockSize, (i - 1) * BlockSize,
BlockSize - 1, BlockSize - 1}
col := Colors[color_idx]
sdl_fill_rect(g.sdl.screen, &rect, &col)
}
fn (g &Game) draw_field() {
for i := 1; i < FieldHeight + 1; i++ {
for j := 1; j < FieldWidth + 1; j++ {
f := g.field[i]
if f[j] > 0 {
g.draw_block(i, j, f[j])
}
}
}
}
fn (g &Game) draw_v_logo() {
if isnil(g.sdl.tv_logo) {
return
}
texw := 0
texh := 0
C.SDL_QueryTexture(g.sdl.tv_logo, 0, 0, &texw, &texh)
dstrect := SDL_Rect { (WinWidth / 2) - (texw / 2), 20, texw, texh }
// Currently we can't seem to use sdl.render_copy when we need to pass a nil pointer (eg: srcrect to be NULL)
// sdl.render_copy(g.sdl.renderer, tv_logo, 0, &dstrect)
C.SDL_RenderCopy(g.sdl.renderer, g.sdl.tv_logo, voidptr(0), voidptr(&dstrect))
}
fn (g &Game) draw_text(x int, y int, text string, tcol SDL_Color) {
_tcol := C.SDL_Color{tcol.r, tcol.g, tcol.b, tcol.a}
tsurf := C.TTF_RenderText_Solid(g.font, text.str, _tcol)
ttext := C.SDL_CreateTextureFromSurface(g.sdl.renderer, tsurf)
texw := 0
texh := 0
C.SDL_QueryTexture(ttext, 0, 0, &texw, &texh)
dstrect := SDL_Rect { x, y, texw, texh }
// sdl.render_copy(g.sdl.renderer, ttext, 0, &dstrect)
C.SDL_RenderCopy(g.sdl.renderer, ttext, voidptr(0), voidptr(&dstrect))
C.SDL_DestroyTexture(ttext)
sdl.free_surface(tsurf)
}
[inline] fn (g &Game) draw_ptext(x int, y int, text string, tcol SDL_Color) {
g.draw_text(g.ofs_x + x, y, text, tcol)
}
[live]
fn (g &Game) draw_begin() {
// println('about to clear')
C.SDL_RenderClear(g.sdl.renderer)
mut rect := SDL_Rect {0,0,g.sdl.w,g.sdl.h}
col := SDL_Color{byte(00), byte(00), byte(0), byte(0)}
// sdl_fill_rect(g.sdl.screen, &rect, BackgroundColor)
sdl_fill_rect(g.sdl.screen, &rect, col)
rect = SDL_Rect {BlockSize * FieldWidth + 2,0,2,g.sdl.h}
sdl_fill_rect(g.sdl.screen, &rect, ForegroundColor)
rect = SDL_Rect {WinWidth - BlockSize * FieldWidth - 4,0,2,g.sdl.h}
sdl_fill_rect(g.sdl.screen, &rect, ForegroundColor)
mut idx := 0
for st in g.tetro_stats {
mut s := 10
if g.tetro_total > 0 {
s += 90 * st / g.tetro_total
}
w := BlockSize
h := s * 4 * w / 100
rect = SDL_Rect {(WinWidth - 7 * (w + 1)) / 2 + idx * (w + 1), WinHeight * 3 / 4 - h, w, h}
sdl_fill_rect(g.sdl.screen, &rect, Colors[idx + 1])
idx++
}
}
fn (g &Game) draw_middle() {
C.SDL_UpdateTexture(g.sdl.texture, 0, g.sdl.screen.pixels, g.sdl.screen.pitch)
// sdl.render_copy(g.sdl.renderer, g.sdl.texture, voidptr(0), voidptr(0))
C.SDL_RenderCopy(g.sdl.renderer, g.sdl.texture, voidptr(0), voidptr(0))
}
fn (g &Game) draw_score() {
if g.font != voidptr(0) {
g.draw_ptext(1, 2, 'score: ' + g.score.str() + ' nxt=' + g.tetro_next.str(), TextColor)
if g.state == .gameover {
g.draw_ptext(1, WinHeight / 2 + 0 * TextSize, 'Game Over', TextColor)
g.draw_ptext(1, WinHeight / 2 + 2 * TextSize, 'FIRE to restart', TextColor)
} else if g.state == .paused {
g.draw_ptext(1, WinHeight / 2 + 0 * TextSize, 'Game Paused', TextColor)
g.draw_ptext(1, WinHeight / 2 + 2 * TextSize, 'SPACE to resume', TextColor)
}
}
}
fn (g &Game) draw_stats() {
if g.font != voidptr(0) {
g.draw_text(WinWidth / 3 + 10, WinHeight * 3 / 4 + 0 * TextSize, 'stats: ' + g.tetro_total.str() + ' tetros', TextColor)
mut stats := ''
for st in g.tetro_stats {
mut s := 0
if g.tetro_total > 0 {
s = 100 * st / g.tetro_total
}
stats += ' '
stats += s.str()
}
g.draw_text(WinWidth / 3 - 8, WinHeight * 3 / 4 + 2 * TextSize, stats, TextColor)
}
}
fn (g &Game) draw_end() {
C.SDL_RenderPresent(g.sdl.renderer)
}
fn parse_binary_tetro(t_ int) []Block {
mut t := t_
res := [Block{}].repeat(4)
mut cnt := 0
horizontal := t == 9// special case for the horizontal line
for i := 0; i <= 3; i++ {
// Get ith digit of t
p := int(math.pow(10, 3 - i))
mut digit := t / p
t %= p
// Convert the digit to binary
for j := 3; j >= 0; j-- {
bin := digit % 2
digit /= 2
if bin == 1 || (horizontal && i == TetroSize - 1) {
// TODO: res[cnt].x = j
// res[cnt].y = i
mut point := &res[cnt]
point.x = j
point.y = i
cnt++
}
}
}
return res
}

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 Nicolas Sauzede
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,60 +0,0 @@
# sdl
SDL2 V module -- libSDL2 wrapper.
Current APIs available/tested in examples:
- basic graphics (2D drawing)
- [Image](image/README.md)
- TTF font (text rendering)
- input handling (keyboard/joystick events)
- sounds (WAV mixing)
- music (MOD mixing)
- more to come.. (networking ?)
## Support
sdl is supported on:
- Linux (major distros)
- MacOS (brew)
- Windows
## Examples
[tVintris](examples/tvintris)
![tVintris screenshot](/examples/sdl/tvintris/images/tvintris.png)
You can run the tVintris example from the V root folder like this :
```
v run vlib/sdl/examples/tvintris/tvintris.v
```
## Dependencies
### Linux
#### Fedora
`$ sudo dnf install SDL2-devel SDL2_ttf-devel SDL2_mixer-devel SDL2_image-devel`
#### Ubuntu
`$ sudo apt install libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev`
#### ClearLinux
`$ sudo swupd bundle-add devpkg-SDL2_ttf devpkg-SDL2_mixer devpkg-SDL2_image`
### MacOS
#### Brew
`$ brew install sdl2 sdl2_gfx sdl2_ttf sdl2_mixer sdl2_image sdl2_net`
If you get no music with the above, try:
`$ brew reinstall --build-from-source --force sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_net sdl2_ttf webp libtiff libmodplug libogg`
### Windows
`$ .github\workflows\windows-install-sdl.bat`
## Contributions
- nsauzede
- spytheman
- adlesh

View File

@ -1,284 +0,0 @@
module sdl
pub union C.SDL_Event {
pub:
@type u32
display C.SDL_DisplayEvent
window C.SDL_WindowEvent
key C.SDL_KeyboardEvent
edit C.SDL_TextEditingEvent
text C.SDL_TextInputEvent
motion C.SDL_MouseMotionEvent
button C.SDL_MouseButtonEvent
wheel C.SDL_MouseWheelEvent
jaxis C.SDL_JoyAxisEvent
jball C.SDL_JoyBallEvent
jhat C.SDL_JoyHatEvent
jbutton C.SDL_JoyButtonEvent
jdevice C.SDL_JoyDeviceEvent
caxis C.SDL_ControllerAxisEvent
cbutton C.SDL_ControllerButtonEvent
cdevice C.SDL_ControllerDeviceEvent
adevice C.SDL_AudioDeviceEvent
sensor C.SDL_SensorEvent
quit C.SDL_QuitEvent
user C.SDL_UserEvent
tfinger C.SDL_TouchFingerEvent
mgesture C.SDL_MultiGestureEvent
drop C.SDL_DropEvent
_pad56 [56]byte
}
// individual event declarations
pub struct C.SDL_DisplayEvent {
@type u32 /**< ::SDL_DISPLAYEVENT */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
display u32 /**< The associated display index */
event byte /**< ::SDL_DisplayEventID */
padding1 byte
padding2 byte
padding3 byte
data1 int /**< event dependent data */
}
pub struct C.SDL_WindowEvent {
pub:
@type u32 /**< ::SDL_WINDOWEVENT */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The associated window */
event byte /**< ::SDL_WindowEventID */
padding1 byte
padding2 byte
padding3 byte
data1 int
data2 int
}
pub struct C.SDL_KeyboardEvent {
pub:
@type u32 /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with keyboard focus, if any */
state byte /**< ::SDL_PRESSED or ::SDL_RELEASED */
repeat byte /**< Non-zero if this is a key repeat */
padding2 byte
padding3 byte
keysym Keysym
}
pub struct C.SDL_TextEditingEvent {
pub:
@type u32 /**< ::SDL_TEXTEDITING */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with keyboard focus, if any */
text [32]byte /**< The editing text */
start int /**< The start cursor of selected editing text */
length int /**< The length of selected editing text */
}
pub struct C.SDL_TextInputEvent {
pub:
@type u32 /**< ::SDL_TEXTINPUT */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with keyboard focus, if any */
text [32]byte /**< The input text */
}
pub struct C.SDL_MouseMotionEvent {
pub:
@type u32 /**< ::SDL_MOUSEMOTION */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with mouse focus, if any */
which u32 /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
state u32 /**< The current button state */
x int /**< X coordinate, relative to window */
y int /**< Y coordinate, relative to window */
xrel int /**< The relative motion in the X direction */
yrel int /**< The relative motion in the Y direction */
}
pub struct C.SDL_MouseButtonEvent {
pub:
@type u32 /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with mouse focus, if any */
which u32 /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
button byte /**< The mouse button index */
state byte /**< ::SDL_PRESSED or ::SDL_RELEASED */
clicks byte /**< 1 for single-click, 2 for double-click, etc. */
padding1 byte
x int /**< X coordinate, relative to window */
y int /**< Y coordinate, relative to window */
}
pub struct C.SDL_MouseWheelEvent {
pub:
@type u32 /**< ::SDL_MOUSEWHEEL */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The window with mouse focus, if any */
which u32 /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
x int /**< The amount scrolled horizontally, positive to the right and negative to the left */
y int /**< The amount scrolled vertically, positive away from the user and negative toward the user */
direction u32 /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
}
pub struct C.SDL_JoyAxisEvent {
pub:
@type u32 /**< ::SDL_JOYAXISMOTION */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick instance id */
axis byte /**< The joystick axis index */
padding1 byte
padding2 byte
padding3 byte
value i16 /**< The axis value (range: -32768 to 32767) */
padding4 u16
}
pub struct C.SDL_JoyBallEvent {
pub:
@type u32 /**< ::SDL_JOYBALLMOTION */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick instance id */
ball byte /**< The joystick trackball index */
padding1 byte
padding2 byte
padding3 byte
xrel i16 /**< The relative motion in the X direction */
yrel i16 /**< The relative motion in the Y direction */
}
pub struct C.SDL_JoyHatEvent {
pub:
@type u32 /**< SDL_JOYHATMOTION */
timestamp u32
which int /**< The joystick device index */
hat byte /**< The joystick hat index */
value byte /**< The hat position value:
* SDL_HAT_LEFTUP SDL_HAT_UP SDL_HAT_RIGHTUP
* SDL_HAT_LEFT SDL_HAT_CENTERED SDL_HAT_RIGHT
* SDL_HAT_LEFTDOWN SDL_HAT_DOWN SDL_HAT_RIGHTDOWN
* Note that zero means the POV is centered.
*/
padding1 byte
padding2 byte
}
pub struct C.SDL_JoyButtonEvent {
pub:
@type u32 /**< SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP */
timestamp u32
which int /**< The joystick device index */
button byte /**< The joystick button index */
state byte /**< SDL_PRESSED or SDL_RELEASED */
padding1 byte
padding2 byte
}
pub struct C.SDL_JoyDeviceEvent {
pub:
@type u32 /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
}
pub struct C.SDL_ControllerAxisEvent {
pub:
@type u32 /**< ::SDL_CONTROLLERAXISMOTION */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick instance id */
axis byte /**< The controller axis (SDL_GameControllerAxis) */
padding1 byte
padding2 byte
padding3 byte
value i16 /**< The axis value (range: -32768 to 32767) */
padding4 u16
}
pub struct C.SDL_ControllerButtonEvent {
pub:
@type u32 /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick instance id */
button byte /**< The controller button (SDL_GameControllerButton) */
state byte /**< ::SDL_PRESSED or ::SDL_RELEASED */
padding1 byte
padding2 byte
}
pub struct C.SDL_ControllerDeviceEvent {
pub:
@type u32 /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
}
pub struct C.SDL_AudioDeviceEvent {
pub:
@type u32 /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which u32 /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
iscapture byte /**< zero if an output device, non-zero if a capture device. */
padding1 byte
padding2 byte
padding3 byte
}
pub struct C.SDL_TouchFingerEvent {
pub:
@type u32 /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
touchId i64 /**< The touch device id */
fingerId i64
x f32 /**< Normalized in the range 0...1 */
y f32 /**< Normalized in the range 0...1 */
dx f32 /**< Normalized in the range -1...1 */
dy f32 /**< Normalized in the range -1...1 */
pressure f32 /**< Normalized in the range 0...1 */
}
pub struct C.SDL_MultiGestureEvent {
pub:
@type u32 /**< ::SDL_MULTIGESTURE */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
touchId i64 /**< The touch device id */
dTheta f32
dDist f32
x f32
y f32
numFingers u16
padding u16
}
pub struct C.SDL_DropEvent {
pub:
@type u32 /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
file byteptr /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
windowID u32 /**< The window that was dropped on, if any */
}
pub struct C.SDL_SensorEvent {
pub:
@type u32 /**< ::SDL_SENSORUPDATE */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
which int /**< The instance ID of the sensor */
data [6]f32 /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
}
pub struct C.SDL_QuitEvent {
pub:
@type u32 /**< SDL_QUIT */
timestamp u32
}
pub struct C.SDL_UserEvent {
pub:
@type u32 /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
timestamp u32 /**< In milliseconds, populated using SDL_GetTicks() */
windowID u32 /**< The associated window if any */
code int /**< User defined event code */
data1 voidptr /**< User defined data pointer */
data2 voidptr /**< User defined data pointer */
}

View File

@ -1,4 +0,0 @@
# SDL2 Image Library
Assuming you've installed the dependencies for sdl (already include `SDL2_image` dependency)
See the Tvintris example for usage

View File

@ -1,68 +0,0 @@
module image
import sdl
#flag linux -lSDL2_image
#flag windows -I @VROOT/thirdparty/SDL2_image/include
#flag windows -L @VROOT/thirdparty/SDL2_image/lib/x64
#flag windows -lSDL2_image
#include <SDL_image.h>
//////////////////////////////////////////////////////////
// SDL_Image.h
//////////////////////////////////////////////////////////
pub const (
IMG_INIT_JPG = 0x00000001
IMG_INIT_PNG = 0x00000002
IMG_INIT_TIF = 0x00000004
IMG_INIT_WEBP = 0x00000008
)
fn C.IMG_Init(flags int) int
fn C.IMG_Quit()
/* Load an image from an SDL data source. The 'type' may be one of: "BMP", "GIF", "PNG", etc. */
fn C.IMG_LoadTyped_RW(src &SDL_RWops, freesrc int, _type byteptr) &SDL_Surface
fn C.IMG_Load(file byteptr) &SDL_Surface
fn C.IMG_Load_RW(src &SDL_RWops, freesrc int) &SDL_Surface
/* Load an image directly into a render texture. */
fn C.IMG_LoadTexture(renderer &SDL_Renderer, file byteptr) &SDL_Texture
fn C.IMG_LoadTexture_RW(renderer &SDL_Renderer, src &SDL_RWops, freesrc int) &SDL_Texture
fn C.IMG_LoadTextureTyped_RW(renderer &SDL_Renderer, src &SDL_RWops, freesrc int, _type byteptr) &SDL_Texture
/* Functions to detect a file type, given a seekable source */
fn C.IMG_isPNG(src &SDL_RWops) int
fn C.IMG_isBMP(src &SDL_RWops) int
fn C.IMG_isJPG(src &SDL_RWops) int
fn C.IMG_isWEBP(src &SDL_RWops) int
/* Individual loading functions */
fn C.IMG_LoadPNG_RW(src &SDL_RWops) &SDL_Surface
fn C.IMG_LoadBMP_RW(src &SDL_RWops) &SDL_Surface
fn C.IMG_LoadJPG_RW(src &SDL_RWops) &SDL_Surface
fn C.IMG_LoadWEBP_RW(src &SDL_RWops) &SDL_Surface
/* Individual saving functions */
fn C.IMG_SavePNG(surface voidptr, file byteptr) int
fn C.IMG_SavePNG_RW(surface voidptr, dst &SDL_RWops, freedst int) int
fn C.IMG_SaveJPG(surface voidptr, file byteptr) int
fn C.IMG_SaveJPG_RW(surface voidptr, dst &SDL_RWops, freedst int) int
pub fn img_init(flags int) int {
return C.IMG_Init(flags)
}
pub fn quit() {
C.IMG_Quit()
}
pub fn load(file string) &SDL_Surface {
res := C.IMG_Load(file.str)
return res
}
pub const (
version = sdl.version // TODO: remove this hack to mark sdl as used; avoids warning
)

View File

@ -1,105 +0,0 @@
module mixer
import sdl
#flag windows -I @VROOT/thirdparty/SDL2_mixer/include
#flag windows -L @VROOT/thirdparty/SDL2_mixer/lib/x64
#flag windows -lSDL2_mixer
#include <SDL_mixer.h>
pub const (
MIX_CHANNEL_POST = -2
MIX_MAX_VOLUME = C.MIX_MAX_VOLUME
MIX_CHANNELS = 8
MIX_DEFAULT_FREQUENCY = 22050
MIX_DEFAULT_FORMAT = C.MIX_DEFAULT_FORMAT
MIX_INIT_FLAC = 0x00000001
MIX_INIT_MOD = 0x00000002
MIX_INIT_MP3 = 0x00000008
MIX_INIT_OGG = 0x00000010
MIX_INIT_MID = 0x00000020
MIX_INIT_OPUS = 0x00000040
)
// Structs
// MIX TODO: get this working as a return type
pub struct C.Mix_Chunk {
allocated int
abuf &byte // *UInt8
alen u32
volume byte /* Per-sample volume, 0-128 */
}
pub struct C.Mix_Music {}
// Methods
// MIX
fn C.Mix_Init(flags int) int
fn C.Mix_OpenAudio(frequency int, format u16, channels int, chunksize int) int
fn C.Mix_CloseAudio()
fn C.Mix_LoadMUS(file byteptr) voidptr // *Mix_Music
fn C.Mix_LoadMUS_RW(src &SDL_RWops, freesrc int) voidptr // *Mix_Music
fn C.Mix_LoadWAV(file byteptr) voidptr // *Mix_Chunk
fn C.Mix_LoadWAV_RW(src &SDL_RWops, freesrc int) voidptr // *Mix_Chunk
// Music
fn C.Mix_FadeInMusic(music &Mix_Music, loops int, ms int) int
fn C.Mix_PlayMusic(music &SDL_AudioSpec, loops int) int
fn C.Mix_VolumeMusic(volume int) int
fn C.Mix_PauseMusic()
fn C.Mix_ResumeMusic()
fn C.Mix_RewindMusic()
fn C.Mix_SetMusicPosition(position f64) int
fn C.Mix_PausedMusic() int
fn C.Mix_HaltMusic() int
fn C.Mix_FadeOutMusic(ms int) int
fn C.Mix_HookMusicFinished(cb fn())
fn C.Mix_FreeMusic(music &Mix_Music)
// Channels
fn C.Mix_VolumeChunk(chunk &Mix_Chunk, volume int) int
fn C.Mix_PlayChannel(channel int, chunk &Mix_Chunk, loops int) int
fn C.Mix_FadeInChannel(channel int, chunk &Mix_Chunk, loops int, ms int) int
fn C.Mix_PlayChannelTimed(channel int, chunk &Mix_Chunk, loops int, ticks int) int
fn C.Mix_Pause(channel int)
fn C.Mix_Resume(channel int)
fn C.Mix_HaltChannel(channel int) int
fn C.Mix_ExpireChannel(channel int, ticks int) int
fn C.Mix_FadeOutChannel(channel int, ms int) int
fn C.Mix_ChannelFinished(cb fn (int))
fn C.Mix_Playing(channel int) int
fn C.Mix_Paused(channel int) int
fn C.Mix_GetChunk(channel int) voidptr //Mix_Chunk
fn C.Mix_FreeChunk(chunk &Mix_Chunk)
fn C.Mix_ReserveChannels(num int) int
// Groups
fn C.Mix_GroupChannel(which int, tag int) int
fn C.Mix_GroupChannels(from int, to int, tag int) int
fn C.Mix_GroupAvailable(tag int) int
fn C.Mix_GroupCount(tag int) int
fn C.Mix_GroupOldest(tag int) int
fn C.Mix_GroupNewer(tag int) int
fn C.Mix_FadeOutGroup(tag int, ms int) int
fn C.Mix_HaltGroup(tag int) int
// Effects
type EffectFunc fn (int, voidptr, int, voidptr) // int chan, void *stream, int len, void *udata
type EffectDone fn (int, voidptr) // int chan, void *udata
fn C.Mix_RegisterEffect(channel int, f EffectFunc, d EffectDone, arg voidptr) int
fn C.Mix_UnregisterEffect(channel int, f EffectFunc) int
fn C.Mix_UnregisterAllEffects(channel int) int
fn C.Mix_SetPanning(channel int, left byte, right byte) int
fn C.Mix_SetDistance(channel int, distance byte) int
fn C.Mix_SetPosition(channel int, angle i16, distance byte) int
fn C.Mix_SetReverseStereo(channel int, flip int) int
pub const (
version = sdl.version // TODO: remove this hack to mark sdl as used; avoids warning
)

View File

@ -1,220 +0,0 @@
// Copyright(C) 2019 Nicolas Sauzede. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module sdl
#flag linux `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image
#flag darwin `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image
#flag solaris `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image
//#flag windows `sdl2-config --cflags`
//#flag windows `sdl2-config --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image
//#flag `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image
#flag -DSDL_DISABLE_IMMINTRIN_H
#flag windows -I @VROOT/thirdparty/SDL2/include
#flag windows -Dmain=SDL_main
#flag windows -lSDL2main -lSDL2
#flag windows -L @VROOT/thirdparty/SDL2/lib/x64
#include <SDL.h>
pub struct C.SDL_RWops {}
pub struct C.SDL_Window {}
pub struct C.SDL_Renderer {}
pub struct C.SDL_Texture {}
pub struct C.SDL_Color{
pub:
r byte
g byte
b byte
a byte
}
pub struct C.SDL_Rect {
pub mut:
x int
y int
w int
h int
}
pub struct C.SDL_Surface {
pub:
flags u32
format voidptr
w int
h int
pitch int
pixels voidptr
userdata voidptr
locked int
lock_data voidptr
clip_rect SDL_Rect
map voidptr
refcount int
}
struct Keysym {
pub:
scancode int /**< hardware specific scancode */
sym int /**< SDL virtual keysym */
mod u16 /**< current key modifiers */
unused u32 /**< translated character */
}
pub struct C.SDL_AudioSpec {
pub mut:
freq int /**< DSP frequency -- samples per second */
format u16 /**< Audio data format */
channels byte /**< Number of channels: 1 mono, 2 stereo */
silence byte /**< Audio buffer silence value (calculated) */
samples u16 /**< Audio buffer size in samples (power of 2) */
size u32 /**< Necessary for some compile environments */
callback voidptr
userdata voidptr
}
// pub struct RwOps {
// pub:
// mut:
// seek voidptr
// read voidptr
// write voidptr
// close voidptr
// type_ u32
// hidden voidptr
// }
//type AudioSpec C.voidptrioSpec
fn C.atexit(func fn ())
///////////////////////////////////////////////////
fn C.SDL_MapRGB(fmt voidptr byte, g byte, b byte) u32
fn C.SDL_CreateRGBSurface(flags u32, width int, height int, depth int, Rmask u32, Gmask u32, Bmask u32, Amask u32) voidptr
fn C.SDL_PollEvent(&SDL_Event) int
fn C.SDL_NumJoysticks() int
fn C.SDL_JoystickNameForIndex(device_index int) voidptr
fn C.SDL_RenderCopy(renderer voidptr, texture voidptr, srcrect voidptr, dstrect voidptr) int
fn C.SDL_CreateWindow(title byteptr, x int, y int, w int, h int, flags u32) voidptr
fn C.SDL_CreateRenderer(window &SDL_Window, index int, flags u32) voidptr
fn C.SDL_CreateWindowAndRenderer(width int, height int, window_flags u32, window &voidptr, renderer &voidptr) int
fn C.SDL_DestroyWindow(window voidptr)
fn C.SDL_DestroyRenderer(renderer voidptr)
fn C.SDL_GetWindowSize(window voidptr, w voidptr, h voidptr)
fn C.SDL_SetHint(name byteptr, value byteptr) C.SDL_bool
//fn C.SDL_RWFromFile(byteptr, byteptr) &RwOps
//fn C.SDL_CreateTextureFromSurface(renderer &C.SDL_Renderer, surface &C.SDL_Surface) &C.SDL_Texture
fn C.SDL_CreateTextureFromSurface(renderer voidptr, surface voidptr) voidptr
fn C.SDL_CreateTexture(renderer voidptr, format u32, access int, w int, h int) voidptr
fn C.SDL_FillRect(dst voidptr, dstrect voidptr, color u32) int
fn C.SDL_SetRenderDrawColor(renderer voidptr, r byte, g byte, b byte, a byte)
fn C.SDL_RenderPresent(renderer voidptr)
fn C.SDL_RenderClear(renderer voidptr) int
fn C.SDL_UpdateTexture(texture voidptr, rect voidptr, pixels voidptr, pitch int) int
fn C.SDL_QueryTexture(texture voidptr, format voidptr, access voidptr, w voidptr, h voidptr) int
fn C.SDL_DestroyTexture(texture voidptr)
fn C.SDL_FreeSurface(surface voidptr)
fn C.SDL_Init(flags u32) int
fn C.SDL_Quit()
fn C.SDL_SetWindowTitle(window voidptr, title byteptr)
// following is wrong : SDL_Zero is a macro accepting an argument
fn C.SDL_zero()
fn C.SDL_LoadWAV(file byteptr, spec voidptr, audio_buf voidptr, audio_len voidptr) voidptr
fn C.SDL_FreeWAV(audio_buf voidptr)
fn C.SDL_OpenAudio(desired voidptr, obtained voidptr) int
fn C.SDL_CloseAudio()
fn C.SDL_PauseAudio(pause_on int)
fn C.SDL_JoystickOpen(device_index int) int
fn C.SDL_JoystickEventState(state int) int
//////////////////////////////////////////////////////////
// SDL_Timer.h
//////////////////////////////////////////////////////////
fn C.SDL_GetTicks() u32
fn C.SDL_TICKS_PASSED(a,b u32) bool
fn C.SDL_GetPerformanceCounter() u64
fn C.SDL_GetPerformanceFrequency() u64
fn C.SDL_Delay(ms u32)
//////////////////////////////////////////////////////////
// GL
//////////////////////////////////////////////////////////
fn C.SDL_GL_SetAttribute(attr int, value int) int
fn C.SDL_GL_CreateContext(window voidptr) voidptr
fn C.SDL_GL_MakeCurrent(window voidptr, context voidptr) int
fn C.SDL_GL_SetSwapInterval(interval int) int
fn C.SDL_GL_SwapWindow(window voidptr)
fn C.SDL_GL_DeleteContext(context voidptr)
pub fn create_texture_from_surface(renderer voidptr, surface &SDL_Surface) voidptr {
return C.SDL_CreateTextureFromSurface(renderer, voidptr(surface))
}
pub fn create_window_and_renderer(width int, height int, window_flags u32, window voidptr, renderer voidptr) int {
return C.SDL_CreateWindowAndRenderer(width, height, window_flags, window, renderer)
}
pub fn joystick_name_for_index(device_index int) byteptr {
return byteptr(C.SDL_JoystickNameForIndex(device_index))
}
pub fn fill_rect(screen &SDL_Surface, rect &SDL_Rect, _col &SDL_Color) {
col := C.SDL_MapRGB(screen.format, _col.r, _col.g, _col.b)
_screen := voidptr(screen)
_rect := voidptr(rect)
C.SDL_FillRect(_screen, _rect, col)
}
pub fn create_rgb_surface(flags u32, width int, height int, depth int, rmask u32, gmask u32, bmask u32, amask u32) &SDL_Surface {
res := C.SDL_CreateRGBSurface(flags, width, height, depth, rmask, gmask, bmask, amask)
return res
}
pub fn render_copy(renderer voidptr, texture voidptr, srcrect &SDL_Rect, dstrect &SDL_Rect) int {
_srcrect := voidptr(srcrect)
_dstrect := voidptr(dstrect)
return C.SDL_RenderCopy(renderer, texture, _srcrect, _dstrect)
}
pub fn poll_event(event &C.SDL_Event) int {
return C.SDL_PollEvent(event)
}
pub fn destroy_texture(text voidptr) {
C.SDL_DestroyTexture(text)
}
pub fn free_surface(surf &SDL_Surface) {
_surf := voidptr(surf)
C.SDL_FreeSurface(_surf)
}
pub fn get_ticks() u32 {
return C.SDL_GetTicks()
}
pub fn ticks_passed(a, b u32) bool {
return C.SDL_TICKS_PASSED(a,b)
}
pub fn get_perf_counter() u64 {
return C.SDL_GetPerformanceCounter()
}
pub fn get_perf_frequency() u64 {
return C.SDL_GetPerformanceFrequency()
}
pub fn delay(ms u32) {
C.SDL_Delay(ms)
}
pub const (
version = '0.2' // hack to avoid unused module warning in the main program
)

View File

@ -1,142 +0,0 @@
module ttf
import sdl
#flag windows -I @VROOT/thirdparty/SDL2_ttf/include
#flag windows -L @VROOT/thirdparty/SDL2_ttf/lib/x64
#flag windows -lSDL2_ttf
#include <SDL_ttf.h>
[typedef]
struct C.TTF_Font {}
fn C.TTF_Init() int
fn C.TTF_Quit()
fn C.TTF_OpenFont(file byteptr, ptsize int) &TTF_Font
fn C.TTF_OpenFontIndex(file byteptr, ptsize int, index i64) &TTF_Font
fn C.TTF_OpenFontRW(src &SDL_RWops, freesrc int, ptsize int) &TTF_Font
fn C.TTF_OpenFontIndexRW(src &SDL_RWops, freesrc int, ptsize int, index i64) &TTF_Font
/* Set and retrieve the font style */
const (
TTF_STYLE_NORMAL = C.TTF_STYLE_NORMAL
TTF_STYLE_BOLD = C.TTF_STYLE_BOLD
TTF_STYLE_ITALIC = C.TTF_STYLE_ITALIC
TTF_STYLE_UNDERLINE = C.TTF_STYLE_UNDERLINE
TTF_STYLE_STRIKETHROUGH = C.TTF_STYLE_STRIKETHROUGH
)
fn C.TTF_GetFontStyle(font &TTF_Font) int
fn C.TTF_SetFontStyle(font &TTF_Font, style int)
fn C.TTF_GetFontOutline(font &TTF_Font) int
fn C.TTF_SetFontOutline(font &TTF_Font, outline int)
/* Set and retrieve FreeType hinter settings */
const (
TTF_HINTING_NORMAL = C.TTF_HINTING_NORMAL
TTF_HINTING_LIGHT = C.TTF_HINTING_LIGHT
TTF_HINTING_MONO = C.TTF_HINTING_MONO
TTF_HINTING_NONE = C.TTF_HINTING_NONE
)
fn C.TTF_GetFontHinting(font &TTF_Font) int
fn C.TTF_SetFontHinting(font &TTF_Font, hinting int)
/* Get the total height of the font - usually equal to point size */
fn C.TTF_FontHeight(font &TTF_Font) int
/* Get the offset from the baseline to the top of the font This is a positive value, relative to the baseline.
*/
fn C.TTF_FontAscent(font &TTF_Font) int
/* Get the offset from the baseline to the bottom of the font This is a negative value, relative to the baseline. */
fn C.TTF_FontDescent(font &TTF_Font) int
/* Get the recommended spacing between lines of text for this font */
fn C.TTF_FontLineSkip(font &TTF_Font) int
/* Get/Set whether or not kerning is allowed for this font */
fn C.TTF_GetFontKerning(font &TTF_Font) int
fn C.TTF_SetFontKerning(font &TTF_Font, allowed int)
/* Get the kerning size of two glyphs */
fn C.TTF_GetFontKerningSizeGlyphs(font &TTF_Font, previous_ch u16, ch u16) int
/* Get the number of faces of the font */
fn C.TTF_FontFaces(font &TTF_Font) i64
/* Get the font face attributes, if any */
fn C.TTF_FontFaceIsFixedWidth(font &TTF_Font) int
fn C.TTF_FontFaceFamilyName(font &TTF_Font) byteptr
fn C.TTF_FontFaceStyleName(font &TTF_Font) byteptr
/* Check wether a glyph is provided by the font or not */
fn C.TTF_GlyphIsProvided(font &TTF_Font, ch u16) int
/* Get the metrics (dimensions) of a glyph To understand what these metrics mean, here is a useful link:
http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
*/
fn C.TTF_GlyphMetrics(font &TTF_Font, ch u16, minx &int, maxx &int, miny &int, maxy &int, advance &int) int
/* Get the dimensions of a rendered string of text */
fn C.TTF_SizeText(font &TTF_Font, text byteptr, w &int, h &int) int
fn C.TTF_SizeUTF8(font &TTF_Font, text byteptr, w &int, h &int) int
fn C.TTF_SizeUNICODE(font &TTF_Font, text &u16, w &int, h &int) int
/* Create an 8-bit palettized surface and render the given text at fast quality with the given font and color. The 0 pixel is the
colorkey, giving a transparent background, and the 1 pixel is set to the text color.
This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderText_Solid(font &TTF_Font, text byteptr, fg SDL_Color) &SDL_Surface
fn C.TTF_RenderUTF8_Solid(font &TTF_Font, text byteptr, fg SDL_Color) &SDL_Surface
fn C.TTF_RenderUNICODE_Solid(font &TTF_Font, text &u16, fg SDL_Color) &SDL_Surface
/* Create an 8-bit palettized surface and render the given glyph at fast quality with the given font and color. The 0 pixel is the
colorkey, giving a transparent background, and the 1 pixel is set to the text color. The glyph is rendered without any padding or
centering in the X direction, and aligned normally in the Y direction. This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderGlyph_Solid(font &TTF_Font, ch u16, fg C.SDL_Color) &SDL_Surface
/* Create an 8-bit palettized surface and render the given text at high quality with the given font and colors. The 0 pixel is background,
while other pixels have varying degrees of the foreground color. This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderText_Shaded(font &TTF_Font, text byteptr, fg SDL_Color, bg SDL_Color) &SDL_Surface
fn C.TTF_RenderUTF8_Shaded(font &TTF_Font, text byteptr, fg SDL_Color, bg SDL_Color) &SDL_Surface
fn C.TTF_RenderUNICODE_Shaded(font &TTF_Font, text &u16, fg SDL_Color, bg SDL_Color) &SDL_Surface
/* Create an 8-bit palettized surface and render the given glyph at high quality with the given font and colors. The 0 pixel is background,
while other pixels have varying degrees of the foreground color. The glyph is rendered without any padding or centering in the X
direction, and aligned normally in the Y direction. This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderGlyph_Shaded(font &TTF_Font, ch u16, fg C.SDL_Color) &SDL_Surface
/* Create a 32-bit ARGB surface and render the given text at high quality, using alpha blending to dither the font with the given color.
This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderText_Blended(font &TTF_Font, text byteptr, fg SDL_Color, bg SDL_Color) &SDL_Surface
fn C.TTF_RenderUTF8_Blended(font &TTF_Font, text byteptr, fg SDL_Color, bg SDL_Color) &SDL_Surface
fn C.TTF_RenderUNICODE_Blended(font &TTF_Font, text &u16, fg SDL_Color, bg SDL_Color) &SDL_Surface
/* Create a 32-bit ARGB surface and render the given text at high quality, using alpha blending to dither the font with the given color.
Text is wrapped to multiple lines on line endings and on word boundaries if it extends beyond wrapLength in pixels.
This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderText_Blended_Wrapped(font &TTF_Font, text byteptr, fg SDL_Color, wrap_length u32) &SDL_Surface
fn C.TTF_RenderUTF8_Blended_Wrapped(font &TTF_Font, text byteptr, fg SDL_Color, wrap_length u32) &SDL_Surface
fn C.TTF_RenderUNICODE_Blended_Wrapped(font &TTF_Font, text &u16, fg SDL_Color, wrap_length u32) &SDL_Surface
/* Create a 32-bit ARGB surface and render the given glyph at high quality, using alpha blending to dither the font with the given color.
The glyph is rendered without any padding or centering in the X direction, and aligned normally in the Y direction.
This function returns the new surface, or NULL if there was an error.
*/
fn C.TTF_RenderGlyph_Blended(font &TTF_Font, ch u16, fg C.SDL_Color) &SDL_Surface
fn C.TTF_WasInit() int
fn C.TTF_CloseFont(font &TTF_Font)
pub const (
version = '0.0.1'
sdl_version = sdl.version // TODO: remove this hack to mark sdl as used; avoids warning
)

View File

@ -1,4 +1,5 @@
fn todo() {}
/*
// QTODO
fn simple<T>(p T) T {

View File

@ -4,6 +4,8 @@ interface Speaker {
say() string
}
fn todo() {}
/*
// QTODO
struct ChatRoom {