mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
examples: add a small memory game (#24643)
This commit is contained in:
parent
366f3d6b98
commit
d7061cbfef
1 changed files with 137 additions and 0 deletions
137
examples/gg/memory.v
Normal file
137
examples/gg/memory.v
Normal file
|
@ -0,0 +1,137 @@
|
|||
module main
|
||||
|
||||
import gg
|
||||
import gx
|
||||
import rand
|
||||
import time
|
||||
|
||||
const cover = gx.rgba(85, 200, 85, 255)
|
||||
const csize = 120 // cell size in pixels
|
||||
const letters = 'AABBOOCCVVXXYYZZMMKKHHTT'.runes().map(it.str())
|
||||
const header_size = 30
|
||||
|
||||
struct Cell {
|
||||
mut:
|
||||
is_open bool
|
||||
letter string
|
||||
}
|
||||
|
||||
struct Game {
|
||||
mut:
|
||||
ctx &gg.Context = unsafe { nil }
|
||||
cells []Cell
|
||||
card1_idx ?int
|
||||
card2_idx ?int
|
||||
size int // in cells
|
||||
remaining int
|
||||
sw time.StopWatch = time.new_stopwatch()
|
||||
revert_sw time.StopWatch = time.new_stopwatch(auto_start: false)
|
||||
}
|
||||
|
||||
fn (mut g Game) restart() {
|
||||
ncells := g.size * g.size
|
||||
g.remaining = ncells
|
||||
g.cells = []Cell{len: ncells, init: Cell{
|
||||
letter: letters[index % letters.len]
|
||||
}}
|
||||
rand.shuffle(mut g.cells) or {}
|
||||
g.sw = time.new_stopwatch()
|
||||
g.card1_idx = none
|
||||
g.card2_idx = none
|
||||
}
|
||||
|
||||
fn (mut g Game) draw_cell(i int, cell Cell) {
|
||||
x, y := i % g.size, i / g.size
|
||||
rect_x, rect_y := x * csize, header_size + y * csize
|
||||
dt := g.sw.elapsed().milliseconds()
|
||||
if g.cells[i].is_open || dt <= 1000 {
|
||||
lsize := 96
|
||||
g.ctx.draw_rect_empty(rect_x + 6, rect_y + 6, csize - 10, csize - 10, gx.light_gray)
|
||||
g.ctx.draw_text(rect_x + csize / 2 - lsize / 3, rect_y + csize / 2 - lsize / 2,
|
||||
g.cells[i].letter, color: gx.yellow, size: lsize)
|
||||
} else {
|
||||
g.ctx.draw_rect_filled(rect_x + 6, rect_y + 6, csize - 10, csize - 10, cover)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_frame(mut g Game) {
|
||||
ws := gg.window_size()
|
||||
g.ctx.begin()
|
||||
message := '(r)estart (esc)ape | remaining: ${g.remaining:02} | time: ${f64(g.sw.elapsed().milliseconds()) / 1000.0:06.1f}s'
|
||||
g.ctx.draw_text(ws.width / 2, 7, message, color: gx.light_gray, size: 22, align: .center)
|
||||
for i, cell in g.cells {
|
||||
g.draw_cell(i, cell)
|
||||
}
|
||||
dt := g.revert_sw.elapsed().milliseconds()
|
||||
if dt > 750 {
|
||||
g.revert_sw = time.new_stopwatch(auto_start: false)
|
||||
if g.card1_idx != none {
|
||||
if g.card2_idx != none {
|
||||
g.cells[g.card1_idx].is_open = false
|
||||
g.cells[g.card2_idx].is_open = false
|
||||
g.card1_idx = none
|
||||
g.card2_idx = none
|
||||
g.remaining = g.cells.count(!it.is_open)
|
||||
}
|
||||
}
|
||||
}
|
||||
g.ctx.end()
|
||||
}
|
||||
|
||||
fn on_event(e &gg.Event, mut g Game) {
|
||||
if e.typ == .key_down {
|
||||
match e.key_code {
|
||||
.escape { g.ctx.quit() }
|
||||
.r { g.restart() }
|
||||
else {}
|
||||
}
|
||||
return
|
||||
}
|
||||
if e.typ != .mouse_down {
|
||||
return
|
||||
}
|
||||
x, y := int(e.mouse_x / csize), int((e.mouse_y - header_size) / csize)
|
||||
if e.mouse_button == .left && g.card2_idx == none {
|
||||
if g.remaining == 0 {
|
||||
g.restart()
|
||||
return
|
||||
}
|
||||
i := y * g.size + x
|
||||
if !g.cells[i].is_open {
|
||||
g.cells[i].is_open = true
|
||||
if g.card1_idx == none {
|
||||
g.card1_idx = i
|
||||
} else {
|
||||
g.card2_idx = i
|
||||
if g.cells[g.card1_idx].letter == g.cells[i].letter {
|
||||
g.card1_idx = none
|
||||
g.card2_idx = none
|
||||
} else {
|
||||
// start a timer, that will be checked in the on_frame callback
|
||||
g.revert_sw.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.remaining = g.cells.count(!it.is_open)
|
||||
if g.remaining == 0 {
|
||||
g.sw.stop()
|
||||
}
|
||||
}
|
||||
|
||||
mut g := &Game{
|
||||
// the CLI argument should be number of pairs, so `size` is even, and the puzzle can be solved:
|
||||
size: arguments()[1] or { '3' }.int() * 2
|
||||
}
|
||||
g.restart()
|
||||
g.ctx = gg.new_context(
|
||||
bg_color: gx.black
|
||||
width: g.size * csize
|
||||
height: header_size + g.size * csize
|
||||
window_title: 'V Memory ${g.size} x ${g.size}'
|
||||
user_data: g
|
||||
frame_fn: on_frame
|
||||
event_fn: on_event
|
||||
sample_count: 2
|
||||
)
|
||||
g.ctx.run()
|
Loading…
Add table
Add a link
Reference in a new issue