summaryrefslogtreecommitdiff
path: root/chapter31/docs/examples
diff options
context:
space:
mode:
Diffstat (limited to 'chapter31/docs/examples')
-rw-r--r--chapter31/docs/examples/Clock.smp128
-rw-r--r--chapter31/docs/examples/Dijkstra.smp9
-rw-r--r--chapter31/docs/examples/README.md6
-rw-r--r--chapter31/docs/examples/TicTacToe.smp3
-rw-r--r--chapter31/docs/examples/TicTacToeGraphical.smp3
5 files changed, 140 insertions, 9 deletions
diff --git a/chapter31/docs/examples/Clock.smp b/chapter31/docs/examples/Clock.smp
new file mode 100644
index 00000000..11449810
--- /dev/null
+++ b/chapter31/docs/examples/Clock.smp
@@ -0,0 +1,128 @@
+// Local clocks; click the button or press Space to switch. Q/Escape exits.
+// Any argument runs ten frames, exercising both faces for smoke tests.
+u32 GREEN=0x62ff70, DIM=0x123d20, BACKGROUND=0x020b05;
+
+val main = { u8[~][] args ->
+ val gfx = sys.gfx;
+ val time = sys.time;
+ // The main Canvas
+ val screen = new sys.draw.Canvas(720,540);
+ if( gfx.open("Simple digital and analog clocks",screen.width,screen.height)!=gfx.OK ) return 1;
+
+ // Button to flip clock style
+ val button = new sys.draw.Button(220,454,280,52,"ANALOG CLOCK");
+ val timers = new sys.time.Timers();
+ u32 frame_id = timers.every(33);
+ if( frame_id==0 ) { gfx.close(); return 1; }
+
+ bool analog=false, held=false;
+ int frames=0, status=gfx.OK;
+
+ // Main event loop
+ while( status==gfx.OK ) {
+ // Did the user press space bar?
+ bool space = gfx.key(' ');
+ // Did the left mouse button go down?
+ bool down = gfx.button(gfx.LEFT);
+ // ANd did it go down over this button?
+ bool click = button.update(gfx.mouseX(),gfx.mouseY(),down);
+ // If clicked, flip the clock mode
+ if( click || (space && !held) ) analog=!analog;
+ held = space;
+ if( gfx.key('Q') ) break;
+ // Change button label
+ button.label = analog ? "DIGITAL CLOCK" : "ANALOG CLOCK";
+ // If the next timer event is the every-33-msec event
+ if( timers.poll(time.monotonic())==frame_id ) {
+ // Draw the clock screen and button
+ _draw(screen,time.now(),analog);
+ button.draw(screen,3,GREEN,BACKGROUND,DIM);
+ // Presne the canvas on screen
+ status = gfx.present(screen.pixels);
+ // Testing only: show 5 frames, flip to analog, show 5 more and exit
+ if( args#>1 ) {
+ frames++;
+ if( frames==5 ) analog=true;
+ if( frames==10 ) break;
+ }
+ }
+ if( status!=gfx.OK ) break;
+ // Stall until next timer event
+ status = gfx.wait(time.remaining(timers.nextDeadline(),time.monotonic()));
+ }
+ gfx.close();
+ return status==gfx.ERROR ? 1 : 0;
+};
+
+val _draw = { !sys.draw.Canvas screen, i64 wall_ms, i64 analog ->
+ val d = sys.time.local(wall_ms);
+ screen.clear(BACKGROUND);
+ screen.text(266,24,"SIMPLE CLOCK",4,GREEN);
+ if( analog ) _analog(screen,d.hour,d.minute,d.second,d.millisecond);
+ else _digital(screen,d.hour,d.minute,d.second);
+ screen.text(298,412,"%(sys.time.formatLocal(wall_ms,sys.time.DATE))",4,GREEN);
+ screen.text(249,520,"SPACE SWITCH Q OR ESC QUIT",2,GREEN);
+};
+
+// a..g bits: top, upper-right, lower-right, bottom, lower-left, upper-left,
+// middle. Faint unlit bars retain the old LED figure-eight silhouette.
+val _digit = { !sys.draw.Canvas c, int x, int y, i64 digit ->
+ int bits=digit==0 ? 0x3f : digit==1 ? 0x06 : digit==2 ? 0x5b :
+ digit==3 ? 0x4f : digit==4 ? 0x66 : digit==5 ? 0x6d :
+ digit==6 ? 0x7d : digit==7 ? 0x07 : digit==8 ? 0x7f : digit==9 ? 0x6f : 0;
+ for( int i=0; i<7; i++ ) {
+ u32 color=(bits&(1<<i))!=0 ? GREEN : DIM;
+ if( i==0 || i==3 || i==6 ) {
+ int dy=i==0 ? 0 : i==3 ? 144 : 72;
+ c.line(x+14,y+dy,x+58,y+dy,10,color);
+ } else {
+ bool right=i==1 || i==2;
+ int dx=right ? 68 : 4, dy=i==1 || i==5 ? 12 : 84;
+ c.line(x+dx,y+dy,x+dx,y+dy+48,10,color);
+ }
+ }
+};
+
+val _digital = { !sys.draw.Canvas c, int hour, int minute, int second ->
+ _digit(c,68,166,hour/10); _digit(c,154,166,hour-hour/10*10);
+ _digit(c,284,166,minute/10); _digit(c,370,166,minute-minute/10*10);
+ _digit(c,500,166,second/10); _digit(c,586,166,second-second/10*10);
+ for( int i=0; i<2; i++ ) {
+ c.fillCircle(254+i*216,214,6,GREEN);
+ c.fillCircle(254+i*216,262,6,GREEN);
+ }
+ c.text(272,352,"LOCAL TIME 24H",3,GREEN);
+};
+// Rational sine approximation, accurate enough for pixel clock geometry.
+// Arguments are nonnegative turns; no additional native math dependency.
+val _sin = { f64 turn ->
+ i64 whole=turn; turn-=whole;
+ bool negative=turn>0.5;
+ f64 x=(negative ? turn-0.5 : turn)*6.283185307179586;
+ f64 product=x*(3.141592653589793-x);
+ f64 numerator=negative ? -16.0 : 16.0;
+ return numerator*product/(49.34802200544679-4*product);
+};
+val _hand = { !sys.draw.Canvas c, f64 turn, int length, int thickness, u32 color ->
+ int x=360+_sin(turn)*length, y=232-_sin(turn+0.25)*length;
+ c.line(360,232,x,y,thickness,color);
+};
+val _analog = { !sys.draw.Canvas c, int hour, int minute, int second, int millisecond ->
+ c.circle(360,232,154,3,GREEN);
+ for( int i=0; i<60; i++ ) {
+ f64 turn=i/60.0;
+ bool major=i-i/5*5==0;
+ int inner=major ? 133 : 143;
+ int x0=360+_sin(turn)*inner, y0=232-_sin(turn+0.25)*inner;
+ int x1=360+_sin(turn)*149, y1=232-_sin(turn+0.25)*149;
+ c.line(x0,y0,x1,y1,major ? 3 : 1,GREEN);
+ }
+ c.text(349,100,"12",2,GREEN); c.text(484,227,"3",2,GREEN);
+ c.text(357,354,"6",2,GREEN); c.text(230,227,"9",2,GREEN);
+ f64 seconds=second+millisecond/1000.0;
+ f64 minutes=minute+seconds/60.0;
+ _hand(c,(hour-hour/12*12+minutes/60.0)/12.0,78,8,GREEN);
+ _hand(c,minutes/60.0,112,5,GREEN);
+ _hand(c,seconds/60.0,128,2,0xc3ffcb);
+ c.fillCircle(360,232,6,GREEN);
+};
diff --git a/chapter31/docs/examples/Dijkstra.smp b/chapter31/docs/examples/Dijkstra.smp
index 768bdd08..a8fcf3da 100644
--- a/chapter31/docs/examples/Dijkstra.smp
+++ b/chapter31/docs/examples/Dijkstra.smp
@@ -3,13 +3,10 @@
// https://sampleprograms.io/projects/dijkstra/
val shortestPath = { !sys.aryi64 matrix, int nodes, int src, int dst ->
- i64 infinity = (1 << 63)-1;
- var dist = new i64[nodes];
+ i64 infinity = sys.integer.MAX_I64;
var visited = new sys.adt.bitset();
- // All nodes are infinitely far from each other
- for( int i=0; i<nodes; i++ ) dist[i] = infinity;
- // Starting point is zero far from starting point
- dist[src] = 0;
+ // All nodes are infinitely far from each other, except the starting point
+ var dist = new i64[nodes]{ int i -> i==src ? 0 : infinity; };
i64 result = -1;
int count = 0;
diff --git a/chapter31/docs/examples/README.md b/chapter31/docs/examples/README.md
index a1d81be2..46965ac0 100644
--- a/chapter31/docs/examples/README.md
+++ b/chapter31/docs/examples/README.md
@@ -10,6 +10,12 @@ The [graphical tic-tac-toe](TicTacToeGraphical.smp) uses the Simple
replay, and Q/Escape to quit. The terminal game below remains available.
Optional [background audio](../audio.md) supplies soft move and win/loss cues.
+The [digital and analog clock](Clock.smp) demonstrates the [time library](../time.md),
+green seven-segment digits, smooth clock hands, and a reusable software button.
+Run `make run-clock CTAGS=`; click the button or press Space to switch faces,
+and Q/Escape to exit. Both faces show system-local time.
+`make clock-example CTAGS=` builds it without starting a window.
+
From `chapter31`, build the tic-tac-toe executable (without starting it):
```sh
diff --git a/chapter31/docs/examples/TicTacToe.smp b/chapter31/docs/examples/TicTacToe.smp
index a710e440..1e0f3ca0 100644
--- a/chapter31/docs/examples/TicTacToe.smp
+++ b/chapter31/docs/examples/TicTacToe.smp
@@ -3,8 +3,7 @@ val main = { u8[~][] args ->
sys.io.p("Tic-tac-toe!\nYou are X; the CPU is O. You go first.\n");
sys.io.p("Press a square's number (no Enter needed), or q/Esc to quit.\n");
sys.io.p("Squares:\n 1 | 2 | 3 \n---+---+---\n 4 | 5 | 6 \n---+---+---\n 7 | 8 | 9 \n\n");
- val board = new u8[9];
- for( int i=0; i<board#; i++ ) board[i]=' ';
+ val board = new u8[9]{ int i -> ' '; }; // Initialize the board
// Draw empty board
_draw(board);
diff --git a/chapter31/docs/examples/TicTacToeGraphical.smp b/chapter31/docs/examples/TicTacToeGraphical.smp
index b4f8bcf4..da77e8f6 100644
--- a/chapter31/docs/examples/TicTacToeGraphical.smp
+++ b/chapter31/docs/examples/TicTacToeGraphical.smp
@@ -12,8 +12,9 @@ val main = { u8[~][] args ->
int result = sys.gfx.present(screen.pixels);
bool mouseHeld = false, keyHeld = false, replayHeld = false;
int hover = -1, frames = 0;
+
while( result==sys.gfx.OK ) {
- result = sys.gfx.poll(true);
+ result = sys.gfx.wait(17);
if( result!=sys.gfx.OK ) break;
if( sys.gfx.key('Q') ) break;
bool down = sys.gfx.button(sys.gfx.LEFT);