├── LICENSE ├── README.md ├── ball.c └── ball.png /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 nspool 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hello-plan9 2 | 3 | A very simple GUI app for Plan 9 from Bell Labs. [This blog post](https://nspool.github.io/2013/02/bouncing-ball/) explains the code in more detail. 4 | 5 | Just a bouncing ball with menu options. Using libdraw to animate the ball and libevent for the menu. 6 | 7 | ![Screenshot](ball.png?raw=true "Screenshot showing window, ball and Exit menu item") 8 | 9 | ## Build Instructions 10 | 11 | To compile and link from a i386 Plan 9 terminal: 12 | 13 | `8c -FTVw ball.c && 8l -o ball ball.8` 14 | -------------------------------------------------------------------------------- /ball.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Ball - a first attempt at Plan 9 graphics programming 3 | * Author: nspool 4 | * Date: 2013-02-19 5 | * Licence: MIT 6 | * / 7 | 8 | /* Build with '8c -FTVw ball.c && 8l -o ball ball.8' */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | void moveball(void); 16 | void initball(void); 17 | 18 | Image *ball; 19 | 20 | Point p; 21 | 22 | /* Menus */ 23 | char *buttons[] = {"exit", 0}; 24 | Menu menu = { buttons }; 25 | 26 | /* Radius of ball */ 27 | int r = 20; 28 | int borderWidth = 4; 29 | 30 | 31 | 32 | /* Change direction of ball if collision 33 | * else move the ball and draw to screen 34 | * The new ball image draws over the previous image 35 | * so there is no need to redraw the whole screen */ 36 | 37 | void 38 | moveball() 39 | { 40 | static Point bp={6, 6}; /* Ball Position */ 41 | static double Δi=4, Δj=4; 42 | 43 | /* Collision detection */ 44 | if(bp.x > p.x - (r*3) || bp.x < -r) Δi = Δi*-1; 45 | if(bp.y > p.y - (r*3) || bp.y < -r) Δj = Δj*-1; 46 | 47 | /* Increment ball position */ 48 | bp.x = bp.x + Δi; 49 | bp.y = bp.y + Δj; 50 | 51 | draw(screen, rectaddpt(screen->r, bp), ball, nil, ZP); 52 | } 53 | 54 | 55 | 56 | /* Graphics library requires this function */ 57 | 58 | void 59 | eresized(int new) 60 | { 61 | if(new && getwindow(display, Refnone) < 0) 62 | sysfatal("can't reattach to window"); 63 | 64 | /* Store new screen coordinates for collision detection */ 65 | p = Pt(Dx(screen->r), Dy(screen->r)); 66 | 67 | /* Draw the background DWhite */ 68 | draw(screen, insetrect(screen->r, borderWidth), 69 | allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DWhite), 70 | nil, ZP); 71 | } 72 | 73 | 74 | /* Draw red ball inside a square of white background 75 | * When ball is drawn at new position, background will 76 | * blot out the previous image */ 77 | 78 | void 79 | initball() 80 | { 81 | Image *brush; 82 | brush=allocimage(display, Rect(0,0,1,1), CMAP8, 1, DRed); 83 | ball=allocimage(display, (Rectangle){(Point){0,0},(Point){r*4,r*4}}, 84 | screen->chan, 0, DWhite); 85 | fillellipse(ball, (Point){r*2,r*2}, r, r, brush, ZP); 86 | } 87 | 88 | 89 | void 90 | main(int argc, char *argv[]) 91 | { 92 | USED(argc, argv); 93 | 94 | Event ev; 95 | int e, timer; 96 | 97 | /* Initiate graphics and mouse */ 98 | if(initdraw(nil, nil, "bouncing ball demo") < 0) 99 | sysfatal("initdraw failed: %r"); 100 | 101 | einit(Emouse); 102 | 103 | /* Start our timer 104 | * move the ball every 5 milliseconds 105 | * unless there is an Emouse event */ 106 | 107 | timer = etimer(0, 5); 108 | 109 | /* Simulate a resize event to draw the background 110 | * and acquire the screen dimensions */ 111 | 112 | eresized(0); 113 | 114 | initball(); 115 | 116 | /* Main event loop */ 117 | 118 | for(;;) 119 | { 120 | e = event(&ev); 121 | 122 | /* If there is a mouse event, the rightmost button 123 | * pressed and the first menu option selected 124 | * then exit.. */ 125 | 126 | if( (e == Emouse) && 127 | (ev.mouse.buttons & 4) && 128 | (emenuhit(3, &ev.mouse, &menu) == 0)) exits(nil); 129 | else 130 | if(e == timer) 131 | moveball(); 132 | } 133 | } 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nspool/hello-plan9/6849cd2bf09c2291d0d78203a9a1837ea7b221f7/ball.png --------------------------------------------------------------------------------